You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++三元表达式为何触发拷贝?true分支执行仍出现拷贝

三元表达式中意外触发拷贝构造的原因分析

问题代码

#include <iostream>
struct X {
    X() = default;
    X(int value) : value(value) {}
    X(const X &x) : value(x.value) {
        std::cout << "copy" << std::endl;    
    }
    int value = 0;  
};

struct Z {
    Z(const X &x) : x(x) {}
    const X &get_x() const {return x;}
    X x;    
};

X get_x(const Z &z) {
    return z.get_x();
}

int main() {
    X x1(2);
    Z z1(x1);
    std::cout << "----" << std::endl;
    const X &x2 = (true) ? z1.get_x() : get_x(z1);    // (1)
    std::cout << "----" << std::endl;
    const X &x3 = (true) ? z1.get_x() : z1.get_x();   // (2)
}

输出结果

copy
----
copy
----

原因解析

核心在于C++三元运算符的结果类型统一规则:

  • 代码中的(2)行,两个分支返回的都是const X&类型,因此三元表达式的结果类型直接是const X&,可以直接绑定到x3,不会触发拷贝。
  • 代码中的(1)行,true分支返回const X&,但false分支返回的是X(值类型)。编译器在编译阶段必须确定三元表达式的唯一结果类型,此时会将引用类型转换为值类型:它会把true分支引用的z1.x拷贝生成一个临时X对象,作为三元表达式的结果,再将x2绑定到这个临时对象。

这个类型转换逻辑是编译期决定的,和运行时实际执行哪个分支无关。哪怕条件是true,编译器依然会生成拷贝代码来满足类型统一要求,因此触发了拷贝构造函数。

另外,开头的第一个copy是创建Z对象z1时,其成员x从x1拷贝初始化导致的,属于预期行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:17:25