【问题标题】:Internal moving std::vector elements and QVector内部移动 std::vector 元素和 QVector
【发布时间】:2012-12-12 18:21:23
【问题描述】:

有两个向量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 标志?

【问题讨论】:

标签: c++ qt gcc stl c++11


【解决方案1】:

由于你的移动操作符可以抛出异常,std::vector 不能使用它。如果操作员在调整大小过程中途抛出异常会怎样?如果它不能抛出异常并且vector实现可以使用它,则声明它noexcept

【讨论】:

  • 我添加了 noexcept 说明符,但 out 没有改变。
  • 因为你的类有一个数据成员。正如规则所说,“没有异常规范的析构函数声明被隐式认为具有与隐式声明相同的异常规范。”
【解决方案2】:

可能对某人有用。

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-12
      • 2013-09-21
      • 2018-02-02
      • 1970-01-01
      • 2012-03-24
      • 2012-05-13
      • 2011-03-18
      相关资源
      最近更新 更多