Item26:避免重载通用引用
通用引用太 “贪婪”,会抢走所有重载匹配
- 通用引用是模板 T&&,对任何类型实参都能精确匹配;
- 普通重载(如
int、const std::string&)需要类型转换 / 提升时,永远赢不过通用引用。
例子:
1 | void logAndAdd(int idx); // 普通重载 |
传 short 时:
- 本想走
int重载(需要类型提升) - 结果通用引用精确匹配,直接抢走调用,导致后续无法转成 string,编译报错。
完美转发构造函数会 “劫持” 拷贝构造
写一个带通用引用构造函数的类:
1 | class Person { |
- 传 非 const 左值 Person(如
Person p; auto clone = p;) - 通用引用构造能生成
Person(Person&),比拷贝构造Person(const Person&)匹配更好 - 结果:本该拷贝,却调用了转发构造,试图用 Person 初始化 string,直接编译崩溃。
继承体系下直接炸锅
派生类的拷贝 / 移动构造,本该调用基类的拷贝 / 移动构造:
1 | class SpecialPerson : public Person { |
结果:Person(rhs) 被解析为通用引用构造,而不是基类拷贝构造,代码直接废掉。
总结
对通用引用函数做重载,通用引用几乎会抢走所有你不想让它接的调用;
完美转发构造函数是极差的设计:
- 劫持非 const 左值的拷贝构造;
- 破坏派生类的拷贝 / 移动逻辑;
解决方案:永远不要在通用引用上做重载,特殊处理逻辑用别的方式实现(下一条款讲)。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 肖恩的博客!
评论
