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

为何代码中无任何拷贝/移动构造函数被调用?(GCC环境)

问题分析:C++移动构造函数未被调用的原因

代码示例

#include <iostream>

using namespace std;

struct foo{
    int x;
    double y;
    double z;

    foo(int x_,double y_,double z_)
    {
        x = x_;
        y = y_;
        z = z_;
    }
    foo(const foo& f){
        cout<<"foo copy for const ref called"<<endl;
        x = f.x;
        y = f.y;
        srand((unsigned ) time(nullptr));
        int z_ = rand();
        z = z_;
        cout<<f.x<<endl;
    }
    foo(foo&& f) {
        cout<<"foo copy for right ref called"<<endl;
        x = f.x;
        y = f.y;
        srand((unsigned ) time(nullptr));
        int z_ = rand();
        z = z_;
        cout<<f.x<<endl;
    }
};

int main()
{
    srand((unsigned ) time(nullptr));
    int rand_ = rand();
    foo f_(foo(rand_, 2, 3));
    cout<<f_.x<<' '<<f_.y<<' '<<f_.z<<endl;
}

运行输出

21862 2 3

疑问

原本预期foo(foo&& f)(移动构造函数)会被调用,且f_.z为随机值,但实际无任何拷贝构造函数被触发,f_.z的值为3,请问这是为什么?


解答

这是因为**复制消除(Copy Elision)规则中的返回值优化(RVO)**在起作用,这是C++标准明确允许的优化行为。

在代码语句foo f_(foo(rand_, 2, 3));中,从语法上看是先构造一个临时foo对象,再用这个临时对象去初始化f_,但C++标准允许编译器直接跳过临时对象的创建步骤,直接在f_的内存空间上调用foo(int, double, double)构造函数完成初始化——完全不需要触发移动或拷贝构造函数。

GCC在默认编译选项下(即使是-O0无优化模式)也会执行这个优化,所以你看不到移动/拷贝构造函数的输出,f_.z直接被初始化为3,而非移动构造函数中生成的随机值。

如果想要强制触发移动构造函数,可以给GCC添加编译选项-fno-elide-constructors,禁用复制消除优化,此时编译器会先创建临时对象,再调用移动构造函数初始化f_,就能得到你预期的输出。

另外注意:即便显式使用std::move包装临时对象(如foo f_(std::move(foo(rand_, 2, 3)));),编译器仍可能执行复制消除;只有加上-fno-elide-constructors选项,才能确保移动构造函数被调用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 19:15:22