我刚刚读到 std::allocator
。在我看来,使用它而不是使用 new
和 delete
更复杂。
使用 allocator
我们必须显式分配堆内存,构造它,销毁它,最后释放内存。那么它为什么被创造出来呢?
在哪些情况下可以使用它,什么时候应该使用它来代替 new 和 delete?
原文由 Mugurel 发布,翻译遵循 CC BY-SA 4.0 许可协议
我刚刚读到 std::allocator
。在我看来,使用它而不是使用 new
和 delete
更复杂。
使用 allocator
我们必须显式分配堆内存,构造它,销毁它,最后释放内存。那么它为什么被创造出来呢?
在哪些情况下可以使用它,什么时候应该使用它来代替 new 和 delete?
原文由 Mugurel 发布,翻译遵循 CC BY-SA 4.0 许可协议
在我看来,使用它而不是使用 new 和 delete 更复杂。
是的,但这并不意味着取代 new
和 delete
,它有不同的用途。
使用分配器,我们必须显式地分配堆内存,构造它,销毁它,然后最终释放内存。
那么它为什么被创造出来呢?
因为有时您希望将分配和构造分为两个步骤(类似于将销毁和释放分为两个步骤)。如果您不想这样做,请不要使用分配器,而是使用 new
。
在哪些情况下可以使用它,什么时候应该使用它来代替 new 和 delete?
当您需要分配器的行为时,显然不是 new
和 delete
的行为!典型的情况是在实现容器时。
考虑以下代码:
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
。
您不要使用分配器来代替 new
和 delete
。
原文由 Jonathan Wakely 发布,翻译遵循 CC BY-SA 4.0 许可协议
3 回答1.1k 阅读✓ 已解决
1 回答1k 阅读✓ 已解决
4 回答797 阅读
1 回答874 阅读
1 回答902 阅读
1 回答672 阅读
1 回答779 阅读
std::allocator
是标准库容器的默认内存分配器,您可以替换自己的分配器。这允许您控制标准容器如何分配内存。但我不认为你的问题是关于std::allocator
具体来说,而是分配内存的策略,然后在该内存中构造对象,而不是使用new T[N]
例如。原因是
new T[N]
不允许您控制调用的构造函数。它迫使您同时构建所有对象。这对于例如std::vector
您只想偶尔分配的目的来说是很糟糕的。使用原始内存分配器,您可以分配一定数量的内存,这决定了您的容量。然后,当用户将项目添加到向量中时(使用他们选择的构造函数),您可以在此内存中就地构造对象。
然后当你用完内存时,你分配更多,通常是两倍。如果
std::vector
使用了new T[N]
,那么每次你想添加或删除元素时都必须重新分配,这对性能来说很糟糕。您还将被迫对所有对象使用默认构造函数,这对std::vector
可以容纳的对象类型施加了不必要的限制。