c++ 为什么我不能用引用变量实现移动构造函数?

lymnna71  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(168)

move构造函数的实现方式通常是这样的:

  1. class Test {
  2. public:
  3. int *ptr;
  4. Test() {
  5. }
  6. Test(Test&& t) {
  7. ptr = t.ptr;
  8. t.ptr = nullptr;
  9. }
  10. };
  11. int main() {
  12. Test t = Test(Test());
  13. return 0;
  14. }

为什么我们不能像这样实现它们:

  1. class Test {
  2. public:
  3. int *ptr;
  4. Test() {
  5. }
  6. Test(Test& t) {
  7. ptr = t.ptr;
  8. t.ptr = nullptr;
  9. }
  10. };
  11. int main() {
  12. Test t = Test(Test());
  13. return 0;
  14. }

第二段代码似乎运行得很好。我不明白为什么我们不能那样做。

0g0grzrc

0g0grzrc1#

你当然能做到。你的代码的用户(包括你未来的自己)会诅咒你。

  1. Test t1;
  2. Test t2(t1); // Surprise! t1 no longer holds a valid pointer

对于一个接受右值的移动构造函数,你必须说你想把它放大:

  1. Test t1;
  2. Test t2(std::move(t1)); // Okay, says what it does
mutmk8jj

mutmk8jj2#

不能将非const左值引用绑定到右值(也就是说,不能使用prvalues和xvalues),所以特殊的构造函数不能用于临时或移动操作。

  1. Test t;
  2. Test t2(std::move(t)); // error: tries to bind a non-const& to an xvalue

在您的例子中,它之所以编译,是因为您使用的是C++17或更高版本,其中Test t = Test(Test());等价于Test t;,因为强制复制/移动省略1)。您的特殊构造函数根本没有使用。只有默认构造函数为。
1)t由相同类型的prvalue初始化,因此= T(...)直接初始化t。参见Copy elision on cppreference

相关问题