C++自定义拷贝构造函数被意外调用 所有对象创建均触发原因求解
问题原因
- 构造函数默认参数位置错误:C++语法要求默认参数必须标注在函数声明处,仅在函数定义中写默认参数时,所有仅可见函数声明的调用点都无法识别默认参数,会导致构造函数匹配逻辑异常。比如你调用
Complex z1(3, 5, "z1")时,声明的四参数构造函数无默认参数,无法匹配三个入参的调用,编译器会尝试寻找其他可匹配的构造函数,甚至触发隐式转换,导致意料之外的拷贝构造被调用。 - 拷贝构造函数定义不规范:你自定义的
Complex(Complex &, string = "None")不符合标准拷贝构造函数的要求,第二个参数设置了默认值,进一步增加了构造函数匹配的歧义性,部分本应调用普通构造函数的场景会错误匹配到这个构造函数。 - 补充:如果你使用的是C++11之前的编译标准,没有强制复制消除机制,代码中生成的Complex临时对象也会触发额外的拷贝构造调用。
代码优化建议
- 修正默认参数位置,将所有默认参数写到函数声明中:
// 类内声明部分 Complex(float, float, string = "None", string = "None"); Complex(float); Complex(); // 拆分标准拷贝构造和带命名的复制构造,去掉默认参数避免匹配歧义 Complex(const Complex&); Complex(Complex &, string); - 使用成员初始化列表初始化类成员,相比构造函数体内赋值效率更高:
Complex::Complex(float x, float y, string givnname, string operation) : a(x), b(y), name(std::move(givnname)), Operation(std::move(operation)) { PrintComp(operation); } - 给不会修改类成员的函数加上
const修饰,支持const对象调用:void PrintComp(string op = "None") const; - 避免全局
using namespace std;,按需引入std命名空间下的内容,比如using std::cout;、using std::string;,防止命名空间污染。 - 给单参数的转换构造函数加上
explicit修饰,避免意料之外的隐式类型转换:explicit Complex(float); - 删除类内未使用的
Operation成员变量,减少冗余代码。
内容的提问来源于stack exchange,提问作者adityanithariya
相关产品推荐
相关产品推荐

