C++令人困惑的C风格转换:转换为引用时为何调用构造函数
核心原因:C风格转换的优先级规则
C语言风格的强制类型转换并不会优先执行reinterpret_cast,而是按照以下固定顺序尝试匹配合法转换:
- 第一步:尝试
const_cast - 第二步:尝试
static_cast(会忽略类成员访问权限限制) - 第三步:尝试
static_cast后追加const_cast - 第四步:尝试
reinterpret_cast - 第五步:尝试
reinterpret_cast后追加const_cast
只要前面某一步的转换合法,就会采用对应的转换逻辑,不会走到后面的reinterpret_cast分支。
最简示例的解释
对于(const B&)a这个转换:
- 编译器首先尝试
static_cast<const B&>(a),发现B存在接收const A&参数的构造函数,符合隐式转换规则。 - 该转换的执行逻辑是:先调用
B::B(const A&)构造一个临时B对象,再将const B&引用绑定到这个临时对象上,因此会触发构造函数的打印逻辑。 - 临时对象的生命周期只维持到当前表达式结束,如果你把这个引用返回或者存储,后续访问就会触发未定义行为。
向量代码的解释
你在TVector4的V3()方法中写的(const TVector3<T> &)*this转换逻辑完全一致:
TVector3存在接收const TVector4<U>&的转换构造函数,编译器匹配到第二步的static_cast就直接采用了。- 转换时会构造一个临时的
TVector3<T>对象,你返回的引用实际指向这个栈上临时对象,函数返回后临时对象立即销毁,因此clang会报returning reference to local temporary object的警告。
符合你预期的修正写法
如果你确定TVector4和TVector3的前三个成员内存布局完全兼容,要达到类似reinterpret_cast的效果,必须显式调用reinterpret_cast:
TVector3<T>& V3() { return reinterpret_cast<TVector3<T>&>(*this); } const TVector3<T>& V3() const { return reinterpret_cast<const TVector3<T>&>(*this); }
注意:该转换的合法性严格依赖两个类的内存布局一致性,不符合标准布局规则的用法会触发未定义行为。
内容的提问来源于stack exchange,提问作者jcxz
相关产品推荐
相关产品推荐

