【问题标题】:C++: rvalue reference constructor and copy-elisionC++:右值引用构造函数和复制省略
【发布时间】:2020-06-06 22:08:43
【问题描述】:

我试图理解右值引用构造函数和赋值运算符。我创建了以下源代码,它应该调用 rvalue 引用构造函数,但它不会发生。我的怀疑是复制省略优化是原因。有谁知道是不是这个原因?另外,如果 copy-elision 是原因,那么代码中右值引用的意义何在?

#include <iostream>
#include <vector>
using namespace std;

class X {
public:
    X() : v{new vector<int>(0)} { }
    X(const X&);
    X(X&&);
    X& operator=(const X& rhs);
    X& operator=(X&& rhs);
private:
   vector<int> *v;
};

X::X(const X& a)
{
    cout << "copy constructor" << endl;
    for (auto p : *(a.v))
        v->push_back(p);
}

X::X(X&& a) : v{a.v}
{
    cout << "rval ref constructor" << endl;
    a.v = nullptr;
}

X& X::operator=(const X& rhs)
{
    cout << "assignment operator" << endl;
    delete v;
    v = new vector<int>();
    for (auto p : *(rhs.v))
        v->push_back(p);
    return *this;
}

X& X::operator=(X&& rhs)
{
    cout << "rval ref assignment op" << endl;
    swap(v, rhs.v);
    return *this;
}

X f0()
{
    return X(); // copy-elision no move called
    // return move(X());
}

int main(int argc, char *argv[])
{
    X x1(f0());

    return 0;
}

【问题讨论】:

  • 是的,您观察到复制省略。但并不总是可以省略副本。尝试添加X x2(std::move(x1)); - 你应该会看到一个调用的移动构造函数。
  • @IgorTandetnik 听起来像是一个答案!
  • 在 C++ 编码时,是否总是添加右值引用构造函数和赋值运算符?或者在测试某些性能并发现有必要之前,您是否会忽略这些?谢谢
  • @notaorb:不,你没有。事实上,如果你能做到,你应该努力avoid defining default methods,即伊戈尔指出的“零规则”。

标签: c++ c++11


【解决方案1】:

将以下内容添加到 main():

X x2(std::move(x1));

这手动表示对象 x1 可以移动以解决复制省略。复制省略并不总是被调用,因此可能存在需要右值引用构造函数和赋值运算符的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-07
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2012-07-19
    • 1970-01-01
    相关资源
    最近更新 更多