C++ 返回const引用的函数搭配三目运算符生成临时对象问题
问题根因
这个现象是C++标准中三目运算符(条件运算符)的值类别和类型统一规则直接导致的,具体逻辑如下:
- 三目运算符
a ? b : c要求两个分支b和c的类型、值类别尽可能对齐,最终整个表达式的类型和值类别由对齐后的结果决定 - 你的代码中两个分支的值类别不匹配:
- 第二个分支
getSomeClassObject的返回值是const MyClass&,属于左值 - 第三个分支
MyClass()是临时对象,属于纯右值
- 第二个分支
- 当两个分支分别是同类型的const左值引用和纯右值时,C++标准会将整个三目表达式的结果判定为纯右值。此时如果第二个分支被命中,会先把返回的左值引用指向的对象拷贝构造出一个临时纯右值对象,再把这个临时对象绑定到你定义的
myReference上,这就是你观察到拷贝发生的原因。
为什么移除三目运算符后拷贝消失?
如果你直接写:
MyClass const & myReference = m_SomeMemberObject->getSomeClassObject( strName );
相当于直接把左值引用绑定到左值上,不需要做类型/值类别的统一转换,自然不会触发拷贝构造。
修复方案
你可以把三目运算符的两个分支都统一为const MyClass&类型的左值,避免临时对象生成,示例如下:
// 方案1:将第三个分支替换为静态空对象的左值引用,对齐值类别 static const MyClass s_emptyObj; MyClass const & myReference = !someOtherObject.isValid() ? m_SomeMemberObject->getSomeClassObject( strName ) : s_emptyObj; // 方案2:替换为立即调用的lambda表达式/if-else分支,逻辑更清晰 MyClass const & myReference = [&]()->MyClass const& { if (!someOtherObject.isValid()) { return m_SomeMemberObject->getSomeClassObject(strName); } static const MyClass emptyObj; return emptyObj; }();
内容的提问来源于stack exchange,提问作者Desperado17
相关产品推荐
相关产品推荐

