【问题标题】:Why does a vector have to move its data members when reallocating为什么向量在重新分配时必须移动其数据成员
【发布时间】:2017-11-28 00:36:36
【问题描述】:

假设一个向量内部包含一个由std::aligned_storage 实例组成的数组,如果aligned_storage 实例正在使用,则该数组实际上包含向量模板所基于的类型的元素。

当向量必须分配一个新的内存块并移动其所有元素时,为什么它调用每个正在使用的元素的移动构造函数然后销毁旧元素?为什么不逐字节复制所有字节并删除旧数组而不调用析构函数?这将使新数组成为旧数组的精确副本,而无需移动和销毁元素的开销。

也许我有点累了,错过了一些非常基本的东西。但我想不出这不起作用的原因。

【问题讨论】:

  • 复制字节不能保证与移动或复制对象相同。对于某些类,它可以完全破坏不变量。幸运的是,对于许多类型,调用移动构造函数实际上只是复制字节,在这种情况下,编译器 + 优化器无论如何都会做你想做的事情。
  • @AlanStokes 你能给我一个这样的例子吗?不幸的是,我想不出一个..
  • 我相信,如果您使用 std::align_storage::type 模板,它将创建可以保存给定类型对象的初始化存储/内存块。与任何其他未初始化的存储一样,对象是使用 [placement new] 创建的,并通过显式的析构函数调用销毁。您可能可以做您在问题陈述中提到的内容,但为什么呢?为什么不使用您知道其行为的内置模板类?看一下; en.cppreference.com/w/cpp/language/new
  • @Drt 你的意思是说为什么向量不能只具有向量模板化类型的内部对象数组?如果是这样,那是因为向量保证它只会构造您想要放入其中的元素数量,而不是例如在重新分配时具有 2 倍的成员数量,即使您只想推送一个额外的元素
  • 不确定你在问什么,但我建议你看看:en.cppreference.com/w/cpp/language/new 关于安置新的讨论似乎解决了你原来的问题。 .. 啊,现在我想我明白了……内存分配给一个设定的大小,如果要更改大小,那么它必须重新分配……操作系统和编译器没有办法这样做

标签: c++ vector


【解决方案1】:

仅仅复制字节是不安全的。例如,假设您的对象有两个成员 p 和 d,而 p 是指向 d 的指针。如果你只是复制字节,你会复制指向 d 的旧位置的 p 的值,该位​​置已被销毁。

这是一个简单的例子,但总的来说,C++ 构造函数、析构函数、复制和移动构造函数的原因是让你的对象比字节序列更“聪明”。成员变量是有意义的,而且你的代码可以理解这个意思,而不是编译器。

【讨论】:

  • 具有讽刺意味的是,std::vector 本身就是执行此操作的类的示例。 (大多数实现都有内联分配的“小向量”优化。)这意味着std::vector 本身不能与memcpy 一起移动。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-27
  • 2022-11-13
  • 1970-01-01
  • 1970-01-01
  • 2011-08-16
  • 2020-06-04
  • 2018-09-19
相关资源
最近更新 更多