You need to enable JavaScript to run this app. C++用同类实例调用构造可编译?自动生成构造是否支持类型转换?
优惠活动
大模型
产品
解决方案
定价
更多

C++用同类实例调用构造可编译?自动生成构造是否支持类型转换?

问题1:自定义无参构造后test t2(t1)可正常编译的原因

C++标准对类特殊成员函数的自动生成有明确规则:只要你没有显式声明拷贝构造函数、移动构造函数、拷贝赋值运算符、移动赋值运算符、析构函数,即便你自定义了默认无参构造函数,编译器仍然会为类隐式生成一个public属性、按成员逐一拷贝的默认拷贝构造函数。

你给出的代码中仅显式定义了带explicit修饰的无参构造,没有对拷贝构造做任何声明,因此test t2(t1)可以正常调用编译器自动生成的拷贝构造函数,编译不会报错。

额外说明:explicit修饰符仅作用于可通过单个参数调用的构造函数,用来禁止隐式类型转换。无参构造加explicit仅会禁止test t = {}这种拷贝初始化形式的默认构造调用,和拷贝构造逻辑完全无关。

// 对应第一段代码
class test{
 public:
 explicit test(){}
};

int main(){
 test t1;
 test t2(t1); // 调用编译器自动生成的默认拷贝构造
 return 0;
}

补充疑问解答

编译器自动生成的默认拷贝构造函数核心设计目标是实现类对象的按值复制语义,并不是专门为了支持类型转换场景。

你提到的test(t1)语法属于显式构造调用,本质就是触发拷贝构造逻辑:

  • 当你没有显式声明拷贝构造函数时,编译器生成的隐式拷贝构造参数为const test&,可以匹配t1这个左值的传参,因此test(t1)可以正常构造临时对象传入call函数。
  • 如果你放开代码中注释的test(test& in)声明,相当于你自定义了一个只能接收非常量左值引用的拷贝构造,此时编译器不会再生成默认拷贝构造,只要t1是可修改的左值,该调用仍然可以正常执行;只有当你自定义的拷贝构造被声明为delete或者参数不匹配时,才会出现编译失败。

你提到的类型转换场景通常指不同类型之间的转换,比如你代码中的test(int in)构造函数,就支持把int类型转换为test类型,explicit修饰符对这类单参数构造的转换行为才会产生约束。

// 对应第二段代码
class test{
 public:
 test(int in){}
 // test(test& in){}
};

void call(test in){} 

int main(){
 test t1(5);
 call(test(t1)); // 触发拷贝构造调用
 return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 14:24:02