我们有一个非常庞大的代码库,有时会出现性能问题。根本不使用移动语义。我想知道如何找到移动语义可能有用的地方。你有任何经验如何本地化这样的地方吗?
2 回答
由于标准容器已更新为尽可能移动元素,因此一个好的起点是存储(按值)在标准容器中的类型。如果您制作它们MoveConstructible
并且MoveAssignable
(并确保noexcept
在可能的情况下进行移动操作,例如std::vector
实际上将移动而不是复制),那么使用这些元素的容器的所有代码都可能受益。
其他候选对象是传递给函数或按值从函数返回的任何重要类型。
当然,另一种方法是解决任何性能问题的常用方法:分析代码并找出慢的地方。如果是由于大量复制,那么考虑是否可以避免复制,如果不能,实现移动语义是否会有所帮助。如果缓慢不是由于大量复制,那么移动语义可能无济于事。
移动构造是一个很棒的功能,因为一旦添加了移动构造函数,您就可以“免费”获得所有性能优势。当然,您可以显式移动对象,但移动构造函数的许多用途实际上是隐式的。
将移动构造函数添加到类后,一些受益的地方(远非详尽列表)将是:
std::vector<T> vec;
vec.push_back(T()); //implicit move into array
std::sort(vec.begin(), vec.end()); //may move if std::swap performs swap
T obj = foo(); //move construct if compiler doesn't apply RVO
T obj2 = obj + T(); //technically same as the line above
关于它的重要部分是,一旦您向类添加了移动构造函数(通常只有几行代码),您无需更改任何其他代码即可开始获得移动的好处!
您最大的收获很可能是在向容器中添加元素的循环中,但是您只需添加一个移动构造函数(通常编写起来很简单),就可以在所有这些领域得到改进。
但是,99% 会从 move 中受益的类是分配内存或资源的类,因为 move 允许您用浅拷贝替换深拷贝。大多数其他类(例如只是记录类型的类)不会从移动中获得任何收益。