简体   繁体   中英

uninitialized memory allocation in c++

I am ware that the std::vector.reserve() method reserves the capacity of a vector, and accessing to a vector which is reserved but not manually initialized with values will lead to an undefined behavior. But I was told that the reserve() method does actually fill something into the allocated memory, so it can't be an uninitialized memory allocation, right? So is there ever a way to allocate uninitialized memory in c++ (like how mcalloc() works for c)?

EDIT: sorry I put the wrong word here, it should be like how mcalloc() works for c. I've changed that.

The undefined behaviour comes from violating the contract of the std::vector interface.

Yes, memory is allocated, so you will not get a memory access violation from that.

No, it is not initialised. It's likely created using new char[N] or somesuch, so it's just a bunch of uninitialised char s providing a "playground" on which the vector can build stuff later.

For an integral element type that's not a problem (unless you're going to be reading the indeterminate values). For class types, that's a problem, as their constructors have not been run and so the objects "do not exist".

Could you hack around it by manually creating objects at that location? Perhaps with placement new? Sure. In fact, that's what the vector does! But you'd still be violating the interface of std::vector , imbuing your program with Undefined Behaviour and so — from a black box perspective — you have to accept that anything might happen, no matter how well you think you hacked around it under the bonnet.

Instead, you can create such an object properly by just, y'know, adding to the vector using its documented interface. So just do that.

When you use the new operator it does not initialize the memory if you are using an integer datatype. Such as char* my_mem = new char[N] . This memory will be uninitialized and can contain any value. However if you had something like std::string my_words = new std::string[N] . Theses would all be initialized to empty strings since it is a class and new calls the default constructor. That being said I would imagine that the reserve function follows this behavior. If it is reserving a class it would call the default constructor and if it is an integer type it would not.

To complement the other answers:

I am ware that the std::vector.reserve(n) method reserves the capacity of a vector

Yes, "reserves the capacity" here involves some kind of memory allocation (but you don't know exactly how much except that it is equal or larger than n elements.

, and accessing to a vector which is reserved but not manually initialized with values will lead to an undefined behavior.

The undefined behavior comes in from using element indices larger than vector::size() . It could be fine for trivial types, like int . or anything that can be used in an uninitialized state.

But I was told that the reserve() method does actually fill something into the allocated memory, so it can't be an uninitialized memory allocation, right?

It is an uninitialized memory allocation, reserve doesn't fill anything because that would defeat the purpose of the reserve optimization. reserve can be expensive (allocation) but it has to be an O(1) operation (ie independent of the size or the capacity).

So is there ever a way to allocate uninitialized memory in c++ (like how mcalloc() works for c)?

In some place you find the suggested to use vector::reserve on an empty vector to have an uninitialized buffer of trivial types. It probably works but it is problematic anyway because you have to store the size of your buffer somewhere else and neither vector::size nor vector::capacity can play that role. You cannot use resize either because that will "overwrite" your elements. That is, that vector cannot be used as such anywhere else in your program.

EDIT: sorry I put the wrong word here, it should be like how mcalloc() works for c. I've changed that.

In C++98, the correct way to get uninitialized memory this is to use std::allocator<T>::allocate/deallocate , IMO.

In C++11 you can use additionally std::unique_ptr<T[]> with automatic management.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM