C ++中未初始化的内存分配

Posted

技术标签:

【中文标题】C ++中未初始化的内存分配【英文标题】:uninitialized memory allocation in c++ 【发布时间】:2016-08-04 10:20:28 【问题描述】:

我知道 std::vector.reserve() 方法保留了向量的容量,并且访问保留但未使用值手动初始化的向量将导致未定义的行为。但是有人告诉我,reserve() 方法实际上确实在分配的内存中填充了一些东西,所以它不可能是未初始化的内存分配,对吧?那么有没有办法在 c++ 中分配未初始化的内存(例如 mcalloc() 如何为 c 工作)?

编辑:对不起,我在这里输入了错误的词,它应该就像 mcalloc() 对 c 的工作方式一样。我已经改变了。

【问题讨论】:

like how calloc() works for c.. 你是在开玩笑还是认真的?这就像 180 度相反的陈述。 calloc 分配初始化内存。有一种方法可以在 C++ 中分配未初始化的内存,就像 malloc 对 C 的工作方式一样:它是使用 malloc。还有一种在 C++ 中分配内存的方法,就像 calloc 对 C 的工作方式一样:使用 calloc 答案有点分歧——您能否澄清std::vector 是您问题的症结还是只是一个例子?是要将未初始化的对象放入向量中,还是干脆自己分配未初始化的内存? 【参考方案1】:

未定义的行为来自违反std::vector接口的约定。

是的,内存已分配,因此您不会因此受到内存访问冲突。

不,它没有被初始化。它很可能是使用new char[N] 或类似的东西创建的,所以它只是一堆未初始化的chars,提供了一个“操场”,向量稍后可以在上面构建东西。

对于不成问题的整数元素类型(除非您要读取不确定的值)。对于类类型,这是一个问题,因为它们的构造函数尚未运行,因此对象“不存在”。

您能否通过在该位置手动创建对象来绕过它?也许与安置新?当然。事实上,这就是向量的作用!但是你仍然会违反std::vector 的接口,给你的程序灌输未定义的行为等等——从黑盒的角度来看——你必须接受任何事情都可能发生,无论你认为你在引擎盖。

相反,您可以通过使用其文档化界面添加到向量来正确创建这样的对象。所以就这样做吧。

【讨论】:

【参考方案2】:

如果您使用整数数据类型,当您使用 new 运算符时,它不会初始化内存。如char* my_mem = new char[N]。该内存将未初始化并且可以包含任何值。但是,如果你有类似std::string my_words = new std::string[N] 的东西。这些都将被初始化为空字符串,因为它是一个类并且 new 调用默认构造函数。话虽如此,我会想象储备功能遵循这种行为。如果它正在保留一个类,它将调用默认构造函数,如果它是整数类型,则不会。

【讨论】:

我希望reserve() 在这种情况下不会调用任何ctors。当演员成本高昂时,这将是昂贵的。 (不过,它可能需要它们在编译时存在,iiuc。)【参考方案3】:

补充其他答案:

我知道 std::vector.reserve(n) 方法保留了容量 一个向量的

是的,这里的“保留容量”涉及某种内存分配(但你不知道具体多少,除非它等于或大于n 元素。

,并且访问保留但未手动使用值初始化的向量将导致未定义的行为。

未定义的行为来自使用大于vector::size() 的元素索引。 对于诸如int 之类的琐碎类型可能没问题。或任何可以在未初始化状态下使用的东西。

但是有人告诉我,reserve() 方法确实会在分配的内存中填充一些东西,所以它不可能是未初始化的内存分配,对吧?

未初始化的内存分配,reserve 不会填充任何内容,因为这会破坏reserve 优化的目的。 reserve 可能很昂贵(分配),但它必须是 O(1) 操作(即与大小或容量无关)。

那么有没有办法在 c++ 中分配未初始化的内存(例如 mcalloc() 如何为 c 工作)?

在某些地方,您会发现建议在空向量上使用 vector::reserve 来获得未初始化的普通类型缓冲区。 它可能有效,但无论如何它都是有问题的,因为您必须将缓冲区的大小存储在其他地方,vector::sizevector::capacity 都不能扮演这个角色。 您也不能使用resize,因为这会“覆盖”您的元素。 也就是说,该向量不能在程序的其他任何地方使用。

编辑:对不起,我在这里输入了错误的词,它应该就像 mcalloc() 对 c 的工作方式一样。我已经改变了。

在 C++98 中,获取未初始化内存的正确方法是使用 std::allocator<T>::allocate/deallocate,IMO。

在 C++11 中,您可以额外使用 std::unique_ptr<T[]> 进行自动管理。

【讨论】:

以上是关于C ++中未初始化的内存分配的主要内容,如果未能解决你的问题,请参考以下文章

VC中未分配空间的内存的处理

c程序代码的内存布局(学好C的基础)

Linux下C程序的存储空间布局

Linux下C程序的存储空间布局

程序运行过程中的内存分配

内存段是如何划分的