【问题标题】:copy-constructor called instead of move-constructor调用复制构造函数而不是移动构造函数
【发布时间】:2018-01-12 15:10:35
【问题描述】:

我有以下课程:

class Component {
  public:
    // Constructor
    explicit Component(const void* data, size_t size)
      : _size(size),
        _data(new int[_size]) {
          (void)memcpy(_data, data, _size);
    }

    // Destructor
    ~Component() {
      delete[] _data;
    }

    // Copy-ctor.
    Component(const Component& o)
      : _size(o._size),
        _data(new uint8_t[_size]) {
     (void)memcpy(_data, o._data, _size);
   }

   // Assignment operator
   Component& operator=(const Component& o) {
     if (this != &o) {
       delete[] _data;
       _size = o.getSize();
       _data = new uint8_t[_size];
       (void)memcpy(_data, o.getData(), _size);
     }
     return *this;
   }

   // Move-constructor
   Component(Component&& o)
     : _size(o._size),
       _data(o._data) {
     o._data = nullptr;
   }

   // Move assignment
   Component& operator=(Component&& o) {
     if (this != &o) {
       delete[] _data;
       _size = o._size;
       _data = o._data;
       o._data = nullptr;
     }
     return *this;
   }

   private:
    size_t _size;
    int _data;
};

我想测试我的移动构造函数。所以我试着做:

void f(Component&& c) {
  Component c2 = c; // Expect to use move-constructor
}
int data[] = { 0, 1 };
Component c{&data[0], sizeof(data)};
f(std::move(c)); // getting a rvalue reference from lvalue reference

但后来我发现调用的是我的复制构造函数而不是移动构造函数。你知道为什么吗?

【问题讨论】:

标签: c++ c++11 copy-constructor move-constructor


【解决方案1】:

在这段代码中

void f(Component&& c)
{
    Component c2 = c; // Expect to use move-constructor
}

c 是一个左值。这就是让您在f 内多次使用它的原因。

&& 参数表明调用者将不再需要该对象,您可以随意掠夺它。但是现在您的函数在概念上是所有者...您调用的子例程不应该掠夺您的对象,除非您依次授予它们权限。

c 设为右值会破坏许多用例,例如:

void f(string&& s)
{
    string inputfilename = s + ".in";
    string outputfilename = s + ".out";
    // use s in some other ways
}

要授予子程序获取参数的权限,请使用std::move

【讨论】:

  • @klaus:不......它接受一个右值(prvalue 或 xvalue),但它是一个左值......直到返回语句,当所有的按值和右值引用参数本地人成为 xvalues。
  • 你能给出讨论上述主题的 c++ 标准的链接吗,我想了解更多
  • @emaditaj:那就是eel.is/c++draft/basic.lval,它很长而且很复杂。第一个示例(实际上是包含多个示例的代码块)以A&& ar = static_cast<A&&>(a); 结尾,注释ar 是一个左值。
【解决方案2】:

看来你需要把 f 改成

void f(Component&& c) {
    Component c2 = std::move(c);
}

然后这样称呼它:

f(c);

请看:similar example

注意:我尚未对其进行测试,但请参阅其他线程的答案以获得解释。

【讨论】:

  • 您仍然需要致电f(std::move(c))
  • 是的,它有效,但我不明白为什么我的解决方案无效!
猜你喜欢
  • 2022-11-21
  • 1970-01-01
  • 2015-06-10
  • 1970-01-01
  • 2022-01-12
  • 2013-04-25
  • 2021-12-25
  • 2016-07-12
相关资源
最近更新 更多