在 C 中使用 std::allocator 而不是 new 有什么好处?

新手上路,请多包涵

我刚刚读到 std::allocator 。在我看来,使用它而不是使用 newdelete 更复杂。

使用 allocator 我们必须显式分配堆内存,构造它,销毁它,最后释放内存。那么它为什么被创造出来呢?

在哪些情况下可以使用它,什么时候应该使用它来代替 new 和 delete?

原文由 Mugurel 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

std::allocator 是标准库容器的默认内存分配器,您可以替换自己的分配器。这允许您控制标准容器如何分配内存。但我不认为你的问题是关于 std::allocator 具体来说,而是分配内存的策略,然后在该内存中构造对象,而不是使用 new T[N] 例如。

原因是 new T[N] 不允许您控制调用的构造函数。它迫使您同时构建所有对象。这对于例如 std::vector 您只想偶尔分配的目的来说是很糟糕的。

使用原始内存分配器,您可以分配一定数量的内存,这决定了您的容量。然后,当用户将项目添加到向量中时(使用他们选择的构造函数),您可以在此内存中就地构造对象。

然后当你用完内存时,你分配更多,通常是两倍。如果 std::vector 使用了 new T[N] ,那么每次你想添加或删除元素时都必须重新分配,这对性能来说很糟糕。您还将被迫对所有对象使用默认构造函数,这对 std::vector 可以容纳的对象类型施加了不必要的限制。

原文由 Benjamin Lindley 发布,翻译遵循 CC BY-SA 3.0 许可协议

在我看来,使用它而不是使用 new 和 delete 更复杂。

是的,但这并不意味着取代 newdelete ,它有不同的用途。

使用分配器,我们必须显式地分配堆内存,构造它,销毁它,然后最终释放内存。

那么它为什么被创造出来呢?

因为有时您希望将分配和构造分为两个步骤(类似于将销毁和释放分为两个步骤)。如果您不想这样做,请不要使用分配器,而是使用 new

在哪些情况下可以使用它,什么时候应该使用它来代替 new 和 delete?

当您需要分配器的行为时,显然不是 newdelete 的行为!典型的情况是在实现容器时。

考虑以下代码:

 std::vector<X> v;
v.reserve(4);        // (1)
v.push_back( X{} );  // (2)
v.push_back( X{} );  // (3)
v.clear();           // (4)

这里第 (1) 行必须为四个对象分配足够的内存,但还没有构造它们。然后第 (2) 和 (3) 行必须将对象构造到分配的内存中。然后第 (4) 行必须销毁这些对象,但不释放内存。最后,在向量的析构函数中,可以释放所有内存。

所以向量不能只使用 new X()delete &m_data[1] 来创建和销毁对象,它必须与构造/销毁分开执行分配/释放。容器的分配器模板参数定义了应该用于(取消)分配内存和构造/销毁对象的策略,允许自定义容器对内存的使用。默认策略是 std::allocator 类型。

因此,当需要分配器时(例如使用容器时),您使用分配器,而当您不想提供自定义分配器而只想要标准分配器时,您使用 std::allocator

您不要使用分配器来代替 newdelete

原文由 Jonathan Wakely 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题