右值引用 - “移动构造函数”有哪些新功能无法在 C++98 中实现?

Ila*_*lan 2 rvalue c++17

我是 C++ 11/17 的新手,试图了解右值引用移动的工作原理。在下面的代码中,“修改的复制构造函数”和“移动构造函数”之间有什么区别?我让他们做同样的事情,但只有不同的原型。如果我在注释中添加“移动构造函数”,那么“修改的复制构造函数”也会执行相同的操作。

我的观点是为什么我们需要“移动构造函数”,现在的 C++17 与旧版本的 C++98 有什么不同?我之前只能通过不同地实现“复制构造函数”来完成同样的事情,并避免它过去所做的所有深度复制。我缺少什么?我不明白的是?

#include <iostream>

class A {
public:
    int* arr, size;
    bool flag;

    // parameterized constructor
    A(int len) {
        size = len;
        arr = new int[size];
        flag = false;
    }

    // modified copy constructor
    A(A& temp) {
        arr = temp.arr;
        size = temp.size;
        flag = temp.flag;
        temp.arr = NULL;
    }

    // move constructor
    A(A&& temp) {
        arr = temp.arr;
        size = temp.size;
        flag = temp.flag;
        temp.arr = NULL;

        std::cout << " A(A&& temp)" << std::endl;
    }

    // destructor
    ~A() {
        delete[] arr;
    }
};

A func()
{
    A obj(100000);
    return obj;
}

int main()
{
    A obj1 = func();
    std::cout << obj1.size << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我期望移动构造函数为 c++98 中无法处理的问题添加新的解决方案

Rem*_*eau 5

对非常量对象(即)的左值引用A&(例如在“修改的”复制构造函数中使用的)不能绑定到右值(即临时对象),但对const对象的左值引用(即const A&A const &)可以。

这就是为什么复制构造函数和复制赋值运算符通常采用const引用。但是,这样做可以防止他们窃取对象的数据(副本无论如何都不应该这样做)。

func()返回一个临时对象,因此它返回一个右值。因此,A obj1 = func();(aka A obj(func());) 不会编译 C++11 之前的版本,除非复制构造函数采用const引用(理应如此)以便绑定到临时对象。

A&&另一方面,右值引用(即)可以绑定到右值(因此得名)。这是 C++11 中添加的最重要的功能,它使移动语义变得实用。

因此,移动构造函数和移动赋值运算符可以从任何非常量对象(特别是临时对象)(例如函数的返回值)窃取数据。而以前,他们只能从预先存在的对象中窃取数据。

  • 事实上,这里的关键功能是“认识到”可靠地高效资源窃取的情况,如果没有成熟的语言支持,这是很难做到的(正如“auto_ptr”尝试过的那样,但失败了)。 (2认同)