我知道std :: vector.reserve()方法保留了向量的容量,并且访问保留但未用值手动初始化的向量将导致未定义的行为。但有人告诉我,reserve()方法实际上会将某些内容填充到已分配的内存中,因此它不能是未初始化的内存分配,对吧?那么有没有办法在c ++中分配未初始化的内存(就像mcalloc()如何为c)工作?
编辑:抱歉,我在这里说错了,应该像mcalloc()的工作原理一样。我已经改变了。答案 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::size
和vector::capacity
都不能扮演那个角色。
您也不能使用resize
,因为那样会“覆盖”您的元素。
也就是说,该向量不能在程序中的其他任何地方使用。
编辑:抱歉,我在这里输入了错误的单词,它应该像mcalloc()对于c的工作方式。我已经改变了。
在C ++ 98中,获取未初始化内存的正确方法是使用IMO std::allocator<T>::allocate/deallocate
。
在C ++ 11中,您还可以将std::unique_ptr<T[]>
与自动管理一起使用。