【问题标题】:Why can't I create a move constructor with the old reference?为什么我不能使用旧引用创建移动构造函数?
【发布时间】:2021-03-08 20:13:40
【问题描述】:

我正在学习如何创建移动构造函数,所以我创建了一个名为 Test 的类,它有一个,就像教程中的那些:

class Test {
private:
    int* arr;
    int size;

public:
    Test() {
        arr = new int[100];
        size = 100;
        for (int i = 0; i < 100; i++) {
            arr[i] = i;
        }
    }

    Test(Test&& other) {
        arr = other.arr;
        size = other.size;
        other.arr = nullptr;
        other.size = 0;
    }
};

出于好奇,我删除了右值引用以查看它是否适用于“旧引用”:

class Test {
private:
    int* arr;
    int size;

public:
    Test() {
        arr = new int[100];
        size = 100;
        for (int i = 0; i < 100; i++) {
            arr[i] = i;
        }
    }

    Test(Test& other) {
        arr = other.arr;
        size = other.size;
        other.arr = nullptr;
        other.size = 0;
    }
};

令我惊讶的是,它运行良好。所以我的问题是: 如果我们之前能够构建完美的移动构造函数,为什么他们将其添加到语言中?

【问题讨论】:

  • std::auto_ptr 会是一本有趣的书,关于我们之前能够做到的事情
  • “它工作得很好” 您是否尝试将不使用右值引用的临时值传递给您的版本? Lets see how well this code works.
  • 不要把它仅仅看作是一个“移动”构造函数,也要把它看作一个rvalue reference构造函数。第二个变体不能处理第一个可以的所有情况,或者一个适当的复制构造函数。事实上,当用作复制构造函数时,其行为会非常令人惊讶。
  • 简短回答 - 因为它会在不应该编译的地方编译,而在应该编译的地方失败。
  • Test(Test&amp; other) 不是move constructor,它是一个copy constructor,它不正确地实现了移动语义而不是复制语义。

标签: c++ move-semantics


【解决方案1】:

根据您的建议,以下第一种和第三种情况会发生同样的事情:

Test someFunction();

Test a;

Test b(a);              // 1. as a developer I wanted a copy 
Test c(someFunction()); // 2. I expect the compiler to move the return value
Test d(std::move(a));   // 3. here, I wanted a move, as I don't care about a anymore

因此,在上述三种情况中,您的建议没有区分第一种和第三种。这就是 r 值引用所提供的:找出上下文并区分可以移动的引用和不能移动的引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-21
    • 2013-08-11
    • 1970-01-01
    相关资源
    最近更新 更多