C++ 调用了复制构造函数而不是移动构造函数

C++ 调用了复制构造函数而不是移动构造函数,c++,c++11,copy-constructor,move-constructor,C++,C++11,Copy Constructor,Move Constructor,我有以下课程: 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() {

我有以下课程:

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

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

看起来你需要把f改成

void f(Component&& c) {
    Component c2 = std::move(c);
}
把它叫做:

f(c);
请参阅:


注意:我还没有测试它,但是请查看其他线程的答案以获得解释。

看起来您需要将f更改为

void f(Component&& c) {
    Component c2 = std::move(c);
}
把它叫做:

f(c);
请参阅:

注意:我还没有测试它,但请参阅其他线程的答案以获得解释。

在这段代码中

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

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

您仍然需要调用
f(std::move(c))
是的,它可以工作,但我不明白我的解决方案为什么不能工作!您仍然需要调用
f(std::move(c))
是的,它可以工作,但我不明白为什么我的解决方案不能工作@克劳斯:不。。。它接受右值(prvalue或xvalue),但它是左值。。。。直到返回语句,当所有按值和rValk引用参数和本地变量变成xValuy时,您能给出链接到C++标准的讨论上面的主题吗,我想读一下。more@emaditaj:那就好了。这是相当长和复杂的。第一个示例(实际上是包含多个示例的代码块)以
a&&ar=static\u cast(a)结尾和注释,
ar
是左值。@克劳斯:不。。。它接受右值(prvalue或xvalue),但它是左值。。。。直到返回语句,当所有按值和rValk引用参数和本地变量变成xValuy时,您能给出链接到C++标准的讨论上面的主题吗,我想读一下。more@emaditaj:那就好了。这是相当长和复杂的。第一个示例(实际上是包含多个示例的代码块)以
a&&ar=static\u cast(a)结尾和注释,
ar
是一个左值。有一个很好的解释。下面是如何:有一个很好的解释。下面是如何: