如何在声明变量后触发拷贝消除以避免调用拷贝/移动构造函数?
问题:如何在预声明变量的场景下实现拷贝消除?
假设有一个按值接收多参数的构造函数:
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
相关产品推荐
相关产品推荐

