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

时间:2016-08-04 10:20:28

标签: c++ c memory-management

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

编辑:抱歉,我在这里说错了,应该像mcalloc()的工作原理一样。我已经改变了。

3 个答案:

答案 0 :(得分:2)

未定义的行为来自违反std::vector界面的合同。

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

不,它没有初始化。它可能是使用new char[N]或其他类似的东西创建的,所以它只是一堆未经初始化的char提供了一个“游乐场”,矢量可以在以后构建内容。

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

你可以通过在该位置手动创建对象来解决它吗?也许放置新的?当然。事实上,这就是矢量的作用!但你仍然违反了std::vector的界面,用未定义的行为来填充你的程序,所以 - 从黑匣子的角度来看 - 你必须接受任何可能发生的事情,不管你认为你在它周围的攻击有多好在引擎盖下。

相反,您可以通过使用其记录的界面添加到矢量来正确创建这样的对象。所以就这样做。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

补充其他答案:

我知道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中,获取未初始化内存的正确方法是使用IMO std::allocator<T>::allocate/deallocate

在C ++ 11中,您还可以将std::unique_ptr<T[]>与自动管理一起使用。