2012-12-27 19 views
7

Istnieją dwa wektory std :: vector i QVector. Musimy sprawdzić, jak elementy "shift" po wstawieniu. (Dwóch wektorów jest wykonana z pięciu elementów i dodaje zerową pozycję) Mam kod:Wewnętrzne elementy ruchome std :: vector i QVector

#include <QVector> 
#include <QTextStream> 

struct MoveTest 
{ 
    int i; 

    MoveTest()      {} 
    MoveTest(const MoveTest& other) {QTextStream(stdout) << "constr copy" << endl;} 
    MoveTest(MoveTest &&other)  {QTextStream(stdout) << "constr move" << endl;} 
    ~MoveTest()      {} 

    inline MoveTest& operator= (const MoveTest& other) {QTextStream(stdout) << "copy" << endl;} 
    inline MoveTest& operator= (MoveTest &&other)  {QTextStream(stdout) << "move" << endl;} 
}; 

int main(int argc, char *argv[]) 
{ 
    QTextStream(stdout) << "std::move:" << endl; 
    MoveTest t1; 
    MoveTest t2(std::move(t1)); 
    t1 = std::move(t2); 

    QTextStream(stdout) << "QVector:" << endl; 
    QVector<MoveTest> qmTest(5); 
    qmTest.insert(qmTest.begin(), MoveTest()); 

    QTextStream(stdout) << "std::vector:" << endl; 
    std::vector<MoveTest> mTest(5); 
    mTest.insert(mTest.begin(), MoveTest()); 

    return 0; 
} 

My wyjście z gcc 4.7.2, QMAKE_CXXFLAGS + = -std = C++ 0x:

std::move: 
constr move 
move 
QVector: 
constr copy 
constr copy 
constr copy 
constr copy 
constr copy 
constr copy 
copy 
copy 
copy 
copy 
copy 
copy 
std::vector: 
constr move 
constr copy 
constr copy 
constr copy 
constr copy 
constr copy 

Jak wstawiać elementy z przesunięciem wewnętrznym bez kopiowania? Jakie flagi GCC są potrzebne?

+0

darem dla ciebie http://thbecker.net/articles/rvalue_references/section_01.html (tak Dostaję emocjonalny te dni ...) – user1824407

+0

możliwe duplikat [Jak wymusić ruch semantyka kiedy wektor rośnie?] (http://stackoverflow.com/questions/8001823/how-to-enforce-move-semantics-when-a-vector-grows) –

Odpowiedz

5

Ponieważ operator przenoszenia może wyrzucić wyjątek, std::vector nie może go użyć. Co by zrobił, gdyby operator wrzucił wyjątek w połowie procesu zmiany rozmiaru? Zadeklaruj to jako noexcept, jeśli nie można wyrzucić wyjątku, a implementacja wektorowa może go użyć.

+0

Jestem dodawany jako jedyny, ale nie został zmieniony . – user1931823

+0

OK! noexcept działa! Ale z komentarzem ~ MoveTest(). Czemu? – user1931823

+0

Ponieważ twoja klasa ma członka danych. Zgodnie z zasadą: "Deklaracja destruktora, która nie ma specyfikacji wyjątków, jest domyślnie uważana za posiadającą tę samą specyfikację wyjątku, co deklaracja domniemana." –

1

Może być przydatne dla kogoś.

struct MoveTest 
{ 
    int i; 

    MoveTest()      {} 
    MoveTest(MoveTest&&) noexcept {std::cout << "constr move\n";} 
    MoveTest(const MoveTest&)  {std::cout << "constr copy\n";} 
    ~MoveTest() noexcept   {} 

    MoveTest& operator= (MoveTest&&) noexcept {std::cout << "move\n"; return *this;} 
    MoveTest& operator= (const MoveTest&)  {std::cout << "copy\n"; return *this;} 
}; 
Q_DECLARE_TYPEINFO(MoveTest, Q_MOVABLE_TYPE); 

int main(int argc, char *argv[]) 
{ 
    std::cout << "std::move:\n"; 
    MoveTest t1; 
    MoveTest t2(std::move(t1)); 
    MoveTest t3(std::move_if_noexcept(t2)); 
    t2 = std::move(t3); 
    t1 = std::move_if_noexcept(t2); 
    std::cout << "\n"; 

    std::cout << "QVector:\n"; 
    QVector<MoveTest> qmTest(5); 
    qmTest.insert(qmTest.begin(), MoveTest()); 
    std::cout << "\n"; 

    std::cout << "std::vector:\n"; 
    std::vector<MoveTest> mTest(5); 
    mTest.insert(mTest.begin(), MoveTest()); 

    return 0; 
} 

Out:

std::move: 
constr move 
constr move 
move 
move 

QVector: 
constr copy 
constr copy 

std::vector: 
constr move 
constr move 
constr move 
constr move 
constr move 
constr move 
0

pewnością pojemniki w QT są zdolne do radzenia sobie z semantyki pojedynek. Uruchom poniższy przykład i przekonaj się sam.

#include <QCoreApplication> 
#include <QVector> 
#include <iostream> 

struct MoveTest 
{ 
    int i; 

    MoveTest()      {} 
    MoveTest(MoveTest&&) noexcept {std::cout << "constr move\n";} 
    MoveTest(const MoveTest&)  {std::cout << "constr copy\n";} 
    ~MoveTest() noexcept   {} 

    MoveTest& operator= (MoveTest&&) noexcept {std::cout << "move\n"; return *this;} 
    MoveTest& operator= (const MoveTest&)  {std::cout << "copy\n"; return *this;} 
}; 
Q_DECLARE_TYPEINFO(MoveTest, Q_MOVABLE_TYPE); 

int main(int argc, char *argv[]) 
{ 
    std::cout << "std::move:\n"; 
    MoveTest t1; 
    MoveTest t2(std::move(t1)); 
    MoveTest t3(std::move_if_noexcept(t2)); 
    t2 = std::move(t3); 
    t1 = std::move_if_noexcept(t2); 
    std::cout << "\n"; 

    std::cout << "QVector:\n"; 
    QVector<MoveTest> qmTest; 
    int i=5; 
    while(i) { 
     qmTest.append(MoveTest()); 
     --i; 
    } 
    std::cout << "\n"; 

    std::cout << "std::vector:\n"; 
    std::vector<MoveTest> mTest(5); 
    mTest.insert(mTest.begin(), MoveTest()); 

    return 0; 
} 

Ponieważ dwa obiekty mają podobne zastosowanie, nie oznacza to, że wszystkie funkcje składowe są takie same. Sprawdź wyjście poniżej. Out:

std::move: 
constr move 
constr move 
move 
move 

QVector: 
constr move 
constr move 
constr move 
constr move 
constr move 

std::vector: 
constr move 
constr move 
constr move 
constr move 
constr move 
constr move 
Press <RETURN> to close this window... 
Powiązane problemy