c++ - 自定义类中的 move 与复制性能

标签 c++ oop c++11 c++14 move-semantics

如果所述类的成员主要是基本类型,如 int 等,与复制构造函数相比,通过 move 构造函数创建类的实例如何(如果有的话)提高性能。 那些成员不是像在复制 ctor 中一样被复制了吗?那么在处理自定义类时, move 什么时候提供更好的性能?

最佳答案

How (if at all) does creating an instance of a class via move ctor improve performance, compared to the copy ctor, if the members of said class are mainly basic types like int etc. aren't those members just copied like in the copy ctor?

在所有成员变量都是按值/POD 的情况下,应该没有任何区别。

So when does move provide better performance, when dealing with custom classes?

move 构造函数仅在新构造的对象可以从已存在的对象“窃取”资源的情况下提供优势。

例如,假设您有一个临时的 std::string,其中包含小说“ war 与和平”的全部内容——全部 1440 页。

在经典的复制构造函数情况下,如果您想将该临时字符串分配给非临时 std::string(例如,成员变量或全局变量或其他),则程序必须执行以下步骤:

  • 释放目标 std::string 可能持有的任何先前缓冲区
  • 分配一个新的缓冲区,该缓冲区的长度为 (1440*chars_per_page) 字节,用于保存目标 std::string
  • 将所有 1440 页数据从临时 std::string 的缓冲区复制到目标 std::string 的缓冲区
  • 删除临时字符串的缓冲区(当临时字符串超出范围时)

如您所见,这会很低效,因为我们复制了大量数据,即使我们实际上并不需要数据的第二个拷贝。由于我们有一个为 std::string 实现的 move 构造函数,但是,C++11 程序可以更智能,只需这样做:

  • 释放目标 std::string 可能持有的任何先前缓冲区
  • 将巨大的缓冲区从临时 std::string 转移到目标 std::string(注意我们所做的只是复制指向-源字符串到目标字符串的缓冲区值;特别是我们不需要复制,甚至不需要读取任何实际的 1440 页数据!)
  • 将临时字符串的指向缓冲区的指针值设置为 NULL(因此它不会尝试释放它或稍后使用它)

...就是这样;我们不必分配第二个大缓冲区然后复制数据 block ,只需通过混合几个指针值就可以实现所需的最终状态。这是一个巨大的性能胜利,我们可以逃脱这样做,因为我们知道临时字符串无论如何都会被删除,所以“窃取”它所持有的内部数据没有坏处。

我不知道 std::string 是否算作一个“自定义类”,但是只要你有一个动态分配内部的类,你就可以在你自己的类中使用相同的技术状态。

关于c++ - 自定义类中的 move 与复制性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45021797/

相关文章:

c++ - boost::bind 打破了严格的别名规则?

C++模板化链表问题

c# - 创建一个n个几乎未知类型的新实例

php - 在 PHP 中设置具有字符串属性名称的对象的属性

c++ - 基于范围的循环 : get item by value or reference to const?

c++ - MSVC查找符号来自何处

c++ - 为什么这个简单的代码会出现语法错误?

php - spl_object_hash 匹配,对象不相同

c++ - 强制 C++11 lambda 捕获变量

c++ - 为什么 std::to_string 没有短重载?为什么没有 noexcept?