6

是的,另一个reallocstd::vector问题。我知道你要说什么,我同意,忘记手动内存分配,只需使用std::vector. 不幸的是,我的教授禁止我使用 STL 中的任何东西来完成这项任务。

所以是的,我有一个动态数组,T我需要它可以调整大小,但我不能使用std::vector. 我可以回到黑暗时代,malloc和家人一起做所有的事情,但如果我能用new那将是非常棒的。

我读过很多帖子,每个人都说“不,你不能这样做,使用std::vector”,但它们都是在 2011 年 8 月之前发布的,我希望自 C+ 出现以来可能会发生一些变化+11。所以告诉我,我是幸运的,还是我必须恢复到 C 风格的内存分配?

4

2 回答 2

10

无论如何,你应该完全避免realloc,因为你不能像那样移动 C++ 对象。

  • 用于buf = new unsigned char[sizeof(T) * capacity]创建新缓冲区
  • 从现在开始将分配的指针转换unsigned char *T *并使用这些指针T
  • 通过“放置”构造新元素new,如new (&buf[i]) T(original_copy)
  • 要将缓冲区复制到更大的缓冲区,请先分配新缓冲区,使用std::uninitialized_copy( not std::copy ),然后使用销毁旧缓冲区中的元素并使用buf[i].~T()释放旧缓冲区delete [] buf

所有这一切都假设您不必担心异常安全,这对于分配来说可能是可以的。
请注意,在现实世界的代码中,您必须保证异常安全,这这要乏味得多。

于 2013-02-25T06:29:07.383 回答
7

问题realloc在于可能会将现有数据移动到不同范围的连续地址。如果它需要这样做,鉴于它是一个 C 函数,数据被复制而没有任何对 C++ 对象生命周期的点头:

  • 不使用复制/移动构造函数
  • 之后不会为源对象调用析构函数

这可能会导致致命的后果 - 例如,当被移动的对象包含仍然指向正在腾出的内存区域中的地址的指针/引用时。

遗憾的是,正常malloc的实现不允许回调钩子允许您用自己的 C++ 安全实现替换内存内容复制代码。如果你确定你可以尝试找到一个更灵活的“malloc”库,但这不太可能值得麻烦和冒险。

因此,在一般情况下,您应该使用new更改容量、复制/移动每个对象以及delete之后的原件。

如果您确定您的数据足够简单,以至于memcpy-style 重定位不会造成不良后果,那么您可以使用realloc(风险自负)。

于 2013-02-25T06:26:18.060 回答