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

如何在声明变量后触发拷贝消除以避免调用拷贝/移动构造函数?

问题:如何在预声明变量的场景下实现拷贝消除?

假设有一个按值接收多参数的构造函数:

Object(A a, B b, C c, D d, ...);

直接就地初始化的写法:

Object obj{{A params...}, {B params}, ...};

这种写法优化效果极佳,因为不会调用任何拷贝或移动构造函数,但可读性较差。

如果改为先声明变量再传参:

A a{A params...};
B b{B params...};
...
Object obj{a, b, ...}; // 可读性更好,但会触发拷贝构造函数

这种方式会为每个参数调用拷贝构造函数。虽然可以用std::move避免拷贝:

A a{A params...};
B b{B params...};
...
Object obj{std::move(a), std::move(b), ...}; // 无拷贝,但会触发移动

但这样又会调用移动构造函数。

我想知道:有没有办法在这种先声明变量的场景下强制触发拷贝消除,达到和就地初始化完全相同的效果?这看起来是编译器能实现的简单优化,但即使开启-O3也做不到。


补充尝试

我发现可以通过带万能引用的模板构造函数实现类似需求:

#include <iostream>

struct A{
    A(){
        std::cout << "A - default\n";
    }
    
    A(A &&a){
        std::cout << "A - move\n";
    }
    
    A(A &a){
        std::cout << "A - copy\n";
    }
};

struct B{
    A a_;
    
    template <typename T>
    // 不确定是否需要std::forward
    explicit B(T &&a): a_(std::move(std::forward<T>(a))){
    }

    static B BCopyElision(){
        return B{A{}};
    }

    static B BCopy(){
        A a{};
        return B(std::move(a));
    }

    static B BMove(){
        A a{};
        return B{std::move(a)};
    }
    
};

int main()
{
    B::BCopyElision();
    // 输出:A - default
    //       A - move
    
    B::BCopy();
    // 输出:A - default
    //       A - move
    
    B::BMove();
    // 输出:A - default
    //       A - move

    return 0;
}

但有没有办法不用这类非必要的模板构造函数就能实现呢?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:20:19