You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何C++中调用移动构造函数而非默认拷贝构造函数?

C++20中拷贝构造函数与构造函数模板的调用疑惑

我使用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++标准定义的移动/拷贝构造函数:

  1. 模板构造函数的匹配优先级更高
    你定义的A(auto &&other)是模板构造函数,并非标准移动构造函数(标准移动构造函数签名必须为A(A&&))。编译器仍会生成默认的拷贝构造函数A(const A&),但在A p2(p1)的场景中,p1是非常量左值,模板构造函数会被实例化为A(A&),这个签名比默认的A(const A&)匹配度更高,因此编译器选择调用该模板构造函数,而非默认拷贝构造函数。

  2. 自定义模板拷贝构造函数的优先级
    当你取消注释A(auto &other)时,该模板构造函数会被实例化为A(A&),同样比默认的A(const A&)匹配优先级更高,因此编译器会调用你自定义的这个构造函数。

  3. 为何修改参数或删除移动构造函数后会调用默认拷贝构造函数
    若将模板构造函数的参数改为const auto &&,实例化后会得到A(const A&&),无法匹配非常量左值p1;此时没有更匹配的构造函数,编译器才会选择默认生成的A(const A&)拷贝构造函数。而删除真正的移动构造函数(A(A&&))并不会影响模板构造函数的匹配逻辑,你观察到的现象本质还是模板构造函数是否能匹配左值参数的问题。

内容的提问来源于stack exchange,提问作者user2565010

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 05:01:11