c++17 - 右值引用 - 'move constructor' 有哪些新功能无法在 C++98 中实现?

标签 c++17 rvalue

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

我的观点是为什么我们需要“移动构造函数”,现在的 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;
}

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

最佳答案

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

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

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

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

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

关于c++17 - 右值引用 - 'move constructor' 有哪些新功能无法在 C++98 中实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75383070/

相关文章:

c++ - 工厂模式和 std::bind 方法

c++ - Constexpr 类采用 const 引用未编译

c++ - CMake:替换接口(interface)目标的编译标志

c++ - 通过显式调用其析构函数和构造函数来重新创建对象

c++ - 为什么它需要一个右值复制构造函数,即使它不会被调用?

c++ - 以在使用临时对象调用时生成编译器错误的方式重载方法

c++ - 非类右值总是有 cv 非限定类型

c++ - 将可修改右值引用绑定(bind)到可修改左值

c++ - 如何在sigaction sa_sigaction中设置类方法?

c++ - "lvalue"和 "rvalue"命名背后的原因是什么?