C++中Class(const Class& c)与Class(Class& c)构造函数的区别及调用时机
非const左值引用构造函数 vs const左值拷贝构造函数的调用时机
嘿,这个问题问得挺到位的,咱们一步一步来理清楚~
首先明确:你定义的Class(Class& c)是一个接受非const左值引用的构造函数,它和标准的const Class&拷贝构造函数是重载关系。标准拷贝构造函数(const Class&版本)能覆盖绝大多数拷贝场景,但这个非const版本的构造函数,只会在特定的、更“精确匹配”的场景下被调用。
什么时候会调用Class(Class& c)?
主要有三类核心场景:
1. 传递非常量左值对象时,编译器优先匹配更精确的重载
当你用一个非const的左值初始化新对象时,如果同时存在const Class&和Class&两个构造函数,编译器会优先选择不需要添加const限定的那个——也就是Class(Class& c)。
修正测试代码就能看到区别:
Class c; // 输出:running Class()... Class cc(c); // 此时会调用Class(Class& c),因为c是非常量左值,非const版本匹配度更高
(你之前的测试例子里输出了const版本,大概率是代码笔误或者测试时的小疏漏,实际编译运行的话,非const左值会优先触发非const引用的构造函数)
2. 显式指定绑定非const左值引用
如果你通过强制类型转换,把对象转成非const左值引用,编译器就会精准匹配对应的构造函数:
Class c; Class cc(static_cast<Class&>(c)); // 显式转成非const引用,调用Class(Class& c)
3. 接收返回非const左值的函数结果
如果有函数返回非const左值引用,用它初始化新对象时,也会触发这个构造函数:
Class& get_non_const_obj() { static Class obj; return obj; } Class d(get_non_const_obj()); // 调用Class(Class& c)
什么时候绝对不会调用Class(Class& c)?
这个构造函数的参数是非const左值引用,所以以下场景完全无法匹配:
- 用const常量对象初始化新对象:
const Class c_const; Class cc(c_const);—— 只能调用const Class&版本 - 用**临时对象(右值)**初始化新对象:
Class cc(Class());—— 临时对象是右值,无法绑定到非const左值引用,会调用const Class&版本 - 用volatile对象初始化新对象:同样无法匹配非const引用的构造函数
额外提醒
标准意义上的“拷贝构造函数”指的是Class(const Class&)(C11之前)或加上移动构造Class(Class&&)(C11及以后)。你定义的Class(Class&)是自定义的重载构造函数,它不属于标准拷贝构造函数的范畴——比如编译器生成默认拷贝构造时,只会生成const Class&版本,不会生成这个非const版本。
内容的提问来源于stack exchange,提问作者Land
相关产品推荐
相关产品推荐

