C++

Effective Modern C++(7): 右值引用、移动、完美转发(2)

Posted by keys961 on June 13, 2022

1. 慎重考虑移动操作

有时候移动操作没那么好,例如:

  • 对象不支持移动,此时会回退为拷贝

  • 移动不会比拷贝快

    • 如:小字符串SSO,数据不存储在堆中,移动不一定比拷贝快
  • 移动不可用:某些上下文要求移动操作noexcept,但该操作没有,可能会被回退为拷贝(取决于库实现)

因此需要多考虑。

2. std::forward失败的场景

完美转发可能失败:

  • 花括号初始化器:模板T推导失败

    • 解决:在外面声明花括号初始化的std::initializer_list变量,再调用,此时T推导为std::initializer_list
  • 0NULL作为空指针:推导出整数类型,不能完美转发

    • 解决:使用nullptr
  • const static的完美转发:若只有声明,没给出定义,链接可能失败

    • 解决:需要给出它的定义
  • 重载函数或模板的名称:当传入的是一个函数(有重载),或者是一个模板函数,当传入它的名称,编译器不知道传入哪个函数实例,从而转发失败

    • 解决:

      • 对于函数重载:使用using定义函数签名,然后强转函数实例

      • 对于模板:特化它

  • 位域:有些编译器支持自定义字段大小,但non-const引用不应该绑定到位域,因为它可能不能被寻址(例如取3~5位的数据),C++不能创建一个指向任意bit的指针(只能任意byte)

    • 解决:将位域字段拷贝出来,再传入函数中