【问题标题】:C++ move constructor called instead of copy constructor调用 C++ 移动构造函数而不是复制构造函数
【发布时间】:2022-11-21 07:31:27
【问题描述】:

我有这段代码的 sn-p,我正在用 g++.exe -std=c++20 编译它:

#include <iostream>
using namespace std;

class A {
public:
  A() = delete;
  A(int value) : value(value) {}
  // A(auto &other) {
  //   cout << "Copy constructor called..." << endl;
  //   value = other.value;
  // }

  void operator=(const auto &other) = delete;

  A(auto &&other) {
    cout << "Move constructor called..." << endl;
    value = other.value;
  }

  ~A() { cout << "Destructor called..." << endl; }

  friend ostream &operator<<(ostream &os, const A &a);

private:
  int value;
};

ostream &operator<<(ostream &os, const A &a) {
  os << a.value;
  return os;
}

int main() {
  A p1(2);
  cout << "p1: " << p1 << endl;
  A p2(p1);

  cout << "p2: " << p2 << " p1: " << p1 << endl;

  return 0;
}

我遇到的问题是,当复制构造函数被注释时,输出是

Move constructor called...
p2: 2 p1: 2
Destructor called...
Destructor called...

如果我取消注释复制构造函数,输出将变为

p1: 2
Copy constructor called...
p2: 2 p1: 2
Destructor called...
Destructor called...

我想知道为什么编译器不调用默认的复制构造函数(当我删除移动构造函数或将其参数更改为 const 时会发生什么,因此它与调用不匹配)。

【问题讨论】:

    标签: c++ gcc


    【解决方案1】:

    在这种情况下,它实际上不是一个移动构造函数,它是一个带有 universal reference 的构造函数,因此它同时采用左值和右值。如果你只想将它限制为右值,你应该使用显式类型:

    A(A &&other) {
      ...
    }
    

    我想知道为什么编译器不调用默认的复制构造函数(当我删除移动构造函数或将其参数更改为 const 时会发生什么,因此它与调用不匹配)。

    请注意,这不会发生,因为如果您显式添加任何移动操作,复制操作将被隐式删除,因此在这种情况下您必须显式添加它:

    A(const A &other) = default;
    

    【讨论】:

    • A(auto&amp;&amp; other) 是一个通用参考吗,因为 auto 可以翻译成 A(auto&amp; &amp;&amp; other) 并折叠成 A(auto&amp; other)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 2022-01-12
    • 2016-03-25
    • 2013-04-25
    • 2021-12-25
    相关资源
    最近更新 更多