移动内部的std::vector元素和QVector

7

有两个向量std::vectorQVector。我们需要检查在插入元素时如何“移动”它们。(构造了两个具有五个元素并插入零元素的向量)我有这段代码:

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

使用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

如何在不复制的情况下使用内部移位插入元素?需要哪些GCC标志?

这是一份礼物送给你:http://thbecker.net/articles/rvalue_references/section_01.html(是的,最近我有点感性...) - user1824407
可能是如何在向量增长时强制使用移动语义?的重复问题。 - David Schwartz
3个回答

5

既然你的移动运算符可能会抛出异常,std::vector就无法使用它。如果运算符在重新调整大小过程中抛出异常,它该怎么办呢?如果它不能抛出异常,则声明为noexcept,然后向量实现可以使用它。


我已经添加了noexcept修饰符,但是输出没有改变。 - user1931823
因为你的类有一个数据成员。根据规则,“没有异常说明的析构函数声明被隐式认为具有与隐式声明相同的异常说明。” - David Schwartz

1

QT中的容器可以处理移动语义。运行下面的示例,亲身体验。

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

两个对象具有相似的用途并不意味着所有成员函数都相同。请查看下面的输出。

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...

1

可能对某人有用。

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

输出:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接