简体   繁体   中英

Internal moving std::vector elements and QVector

There are two vectors std :: vector and QVector . We have to check how "shift" elements when inserted. (Is constructed two vectors with the five elements and inserted zero element) I've this code:

#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 output with 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

How to insert elements with an internal shift without copying? What GCC flags are needed?

Since your move operator can throw an exception, std::vector can't use it. What would it do if the operator threw an exception halfway through the resize process? Declare it noexcept if it cannot throw an exception and the the vector implementation can use it.

May be useful to someone.

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

Surely containers in QT are capable of coping with move semantics. Run the example below and see for yourself.

#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;
}

Since two objects have similar use that doesn't mean that all member functions are the same. Check output below. 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...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM