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

uninitialized memory allocation in c++

本文关键字:内存 分配 初始化 c++      更新时间:2023-10-16

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

编辑:很抱歉,我把这个词放错了,它应该像mcalloc()对c的作用一样。我已经改变了。

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

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

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

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

你能通过在那个位置手动创建对象来绕过它吗?也许有新的职位?当然事实上,向量就是这样做的!但你仍然违反了std::vector的界面,给你的程序注入了未定义的行为等等;从黑匣子的角度来看;你必须接受任何事情都可能发生,无论你认为你在幕后做得多么好。

相反,你可以通过使用它的文档接口添加到向量中来正确地创建这样一个对象。所以就这么做吧。

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

补充其他答案:

我知道std::vector.reReserve(n)方法保留容量矢量

是的;保留容量";这里涉及到某种内存分配(但除了它等于或大于n元素之外,您不知道确切的内存分配量。

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

未定义的行为来自于使用大于vector::size()的元素索引。对于像int这样的琐碎类型,它可能很好。或者任何可以在未初始化状态下使用的东西。

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

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

那么,有没有一种方法可以在c++中分配未初始化的内存(比如mcalloc()如何为c工作)?

在某些地方,您会发现建议在空向量上使用vector::reserve,以具有琐碎类型的未初始化缓冲区。它可能有效,但无论如何都是有问题的,因为你必须将缓冲区的大小存储在其他地方,而vector::sizevector::capacity都不能起到这个作用。您也不能使用CCD_ 17,因为这将";重写";你的元素。也就是说,该向量不能在程序中的其他任何地方使用。

编辑:很抱歉,我把这个词放错了,它应该像mcalloc()对c的作用一样。我已经改变了。

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

在C++11中,您可以额外使用具有自动管理功能的std::unique_ptr<T[]>