为何用auto定义拷贝构造函数仍触发隐式删除构造函数报错?
问题:使用auto定义构造函数为何仍触发“拷贝构造函数已删除”错误?
以下是编写的C++代码,尝试定义移动构造函数,并使用auto参数定义拷贝构造函数:
#include <iostream> using namespace std; class A { public: A() = delete; A(int value) : value(value) {} void operator=(const auto &other) = delete; ~A() { cout << "Destructor called..." << endl; } A(const auto &other) { cout << "Copy constructor called..." << endl; value = other.value; } A(const A &&other) { cout << "Move constructor called..." << endl; value = other.value; } private: int value; }; int main() { A p1(2); A p2(p1); return 0; }
编译时出现错误:
main.cpp:27:10: error: use of deleted function 'constexpr A::A(const A&)'
按照C++规则,当类定义了移动构造函数时,编译器会隐式删除默认的拷贝构造函数和拷贝赋值运算符,需要显式定义才能使用拷贝操作。但这里用auto参数定义了构造函数,按道理auto会被推导为A类型,为何编译器仍认为拷贝构造函数被删除?
解答
auto参数的构造函数并非标准拷贝构造函数
C++标准明确规定,拷贝构造函数的签名必须是A(const A&)(或A(A&)等带cv限定的同类型引用形式)。使用const auto &other作为参数的构造函数本质是一个模板构造函数,不属于编译器认定的“拷贝构造函数”范畴。编译器只会将符合特定签名的非模板构造函数视为显式定义的拷贝构造函数,因此即使你写了这个模板版本,编译器依然会因为移动构造函数的存在,隐式删除默认的拷贝构造函数。重载解析优先选择非模板版本
即使模板构造函数可以推导出A(const A&)的匹配形式,在重载解析阶段,编译器会优先选择非模板的函数。这里被隐式删除的默认拷贝构造函数属于非模板函数,优先级高于模板构造函数。所以当执行A p2(p1)时,编译器首先匹配到被删除的拷贝构造函数,直接抛出错误,不会去考虑模板版本的构造函数。模板构造函数的适用场景
这个带auto参数的模板构造函数,只能用于从其他类型(而非A类型)初始化A对象的场景,永远无法替代真正的拷贝构造函数完成同类型拷贝。
内容的提问来源于stack exchange,提问作者user2565010
相关产品推荐
相关产品推荐

