C++中Abc类构造器选型:A+B还是C?现代C++优化是否可信?
关于Abc类构造器的选择问题
核心结论
结合你的场景(Def类拷贝成本极高、移动成本低,且构造Abc后仍需保留原Def对象),最优方案是同时提供B(const引用拷贝构造器)+ A(移动构造器);如果想简化代码,也可以只提供C(值传递构造器),现代C++的优化能避免冗余拷贝,但要注意场景限制。
逐个问题拆解
1. 早年值传递(C选项)的两次拷贝问题
早年C++(C++11之前)没有移动语义,值传递构造器确实会导致两次拷贝:
- 第一步:调用
Abc构造器时,实参Def对象会被拷贝到形参; - 第二步:形参再被拷贝到
Abc的成员变量里。
两次大内存拷贝的开销完全无法接受。
2. 现代C++对值传递的优化是否属实?
属实。C++11引入移动语义后,编译器会根据实参的类型自动选择拷贝或移动:
- 如果实参是左值(比如你场景中需要保留的原
Def对象),编译器会将值传递的过程优化为「一次拷贝」(甚至可能直接省略拷贝,即NRVO优化); - 如果实参是右值(比如临时
Def对象、或者用std::move()显式转换的对象),编译器会触发移动操作,把形参的资源直接转移到Abc的成员,完全避免拷贝。
3. 仅保留C构造器的情况
如果只提供值传递构造器Abc(Def d):
- 编译器不会自动改成引用传递,它还是会按值传递的逻辑处理,但会通过移动语义或NRVO优化来减少拷贝;
- 但在你的场景中,因为构造
Abc后还要用原Def对象,所以你只能传入左值,这时候编译器会做一次拷贝(或者NRVO省略拷贝),开销还是存在。而如果同时提供B和A:- 传入左值时,会调用
Abc(const Def& d),直接拷贝一次(或者可能被优化); - 传入右值时,调用
Abc(Def&& d),直接移动,开销极低。
- 传入左值时,会调用
针对你的场景的建议
因为Def拷贝成本极高,且你需要保留原对象,所以:
- 必须提供B(const引用拷贝构造器),确保传入左值时只做一次必要的拷贝;
- 同时提供A(移动构造器),方便在需要传入临时对象或可转移的
Def对象时,用移动代替拷贝,节省开销; - 如果你想简化代码,只写值传递构造器也能工作,但不如同时提供A+B灵活,且某些情况下可能无法触发最优的优化。
内容的提问来源于stack exchange,提问作者no one special
相关产品推荐
相关产品推荐

