C++11右值绑定const左值引用未优化及重载函数代码复用问题咨询
关于func2始终调用拷贝赋值的原因
这是C++语言规则明确约束的行为,不属于编译器可优化的范畴:
func2的第二个参数是const MyClass&类型的const左值引用,虽然可以绑定右值,但绑定后参数c本身是带const修饰的左值(所有有名称的变量本身都是左值,和其绑定的源类型无关)。- 移动赋值运算符的签名为
operator=(MyClass&&),只能接收非const的右值引用,无法匹配const左值类型的参数,重载决议阶段只会选中拷贝赋值运算符operator=(const MyClass&)。 - 标准仅允许编译器在RVO、拷贝消除等明确指定的场景下跳过特殊成员函数调用,而临时对象绑定到引用后已经不符合拷贝消除的适用条件,因此编译器没有权限修改重载决议结果直接调用移动赋值。
避免func3代码重复的最优方案
你之前尝试的func4、func5存在额外拷贝构造+移动赋值的开销,本质是绕远路了,直接使用转发引用(万能引用)+ 完美转发的单模板方案即可实现和func3完全等价的效果,无任何额外开销:
// 仅支持同类型赋值的版本 template<typename T> void func(T& el, T&& c) { el = std::forward<T>(c); } // 兼容任意可赋值类型的通用版本 template<typename T, typename U> void func(T& el, U&& c) { el = std::forward<U>(c); }
该方案利用C++的引用折叠规则自动匹配不同参数类型:
- 传入右值时,模板参数推导为非引用类型,
std::forward返回右值引用,调用移动赋值 - 传入左值时,模板参数推导为左值引用类型,
std::forward返回左值引用,调用拷贝赋值
运行行为和func3的两个重载完全一致,且不需要重复编写函数逻辑。
内容的提问来源于stack exchange,提问作者Millán
相关产品推荐
相关产品推荐

