为了兼顾性能和功能性,有些类会提供拷贝和移动两个版本:
1 | class Widget { |
使用完美转发来实现一个简易版本:
1 | class Widget { |
但通用引用可以接收各种类型的参数,这在传入错误的参数时,编译器的报错信息会异常繁琐。其实还有更好的选择。
如果使用值传递:
1 | class Widget { |
对于 c++ 11,如果传入的参数是左值,则会进行一次拷贝构造。而如果传入的是右值,则进行的是移动构造:
1 | Widget w; |
下面比较这 3 种方法的性能:
- 拷贝构造和移动构造:传入左值时,会进行一次拷贝。传入右值时,会进行一次移动。
- 完美转发构造:完美转发会匹配对应的左值和右值函数,所以性能和方法 1 一样
- 值传递:传入左值时,一次拷贝加一次移动。传入右值时,两次移动
- 首先是构造形参,传入左值时,会调用拷贝构造函数。传入右值时,会调用移动构造函数(
std::string
具有移动构造函数)。 - 然后是将形参移动到内部容器中
- 首先是构造形参,传入左值时,会调用拷贝构造函数。传入右值时,会调用移动构造函数(
可以看到,方法 3 相比方法 1,2 多了一次移动操作,如果移动操作耗时很低,那么可以考虑使用方法 3。
因为方法 3 足够简单,阅读性也好。