How does vector calls copy constructor on specific location? - c++

I was wondering how vector works in C++. When we add a new element and the vector runs out of the space, it allocates a new memory and copies all the previous elements to the new location.
Now, how this behavior is defined?
A* a = new A(prev_a);
will copy construct at new location allocated by new. But for vector, we have to allocate multiple objects. But we cannot do so because array new cannot have initialization arguments.
So I wonder, how does vector implement this? I assume that the vector allocate a memory first and calls a copy constructor at the specific location. How is this done? Thanks

I assume that the vector allocate a memory first and calls a copy constructor at the specific location.
That is right, these are two separate steps:
Memory allocation using allocator::allocate.
Initialization. It copy/move-constructs the elements using allocator::construct, which normally uses placement new.

Related

std::vector vs dynamic array passing by value

Hello I am comming from c to c++ and I've been wondering why can std::vector be passed by value.
I assume passing dynamicaly allocated array by value is not possible as that would only copy the pointer.
How is it then possible for a vector to be coppied, if inside of a vector class is same pointer. It has to somehow know how to reconstruct it into another object.
std::vector knows how many elements are stored in the dynamic memory. It is a simple matter to allocate a new buffer of that size and copy the contents into that new memory. All of this happens in the copy constructor.

C++ When to use pointer to vector?

I have a problem about pointer and standard library use.
Let's create a new class
class Graph
{
std::vector<Edge> *edge_list;
//another way is
//std::vector<Edge> edge_list;
}
I already thought two reasons why I use pointer:
It's easy to manipulate the memory using new and delete
It can be passed by parameters easily.
However, we can pass by reference if we use vector.Then Reason 2 doesn't count.
So, Is it true if I am not strict with memory allocation, I don't need to use pointer to vector and other std container?
The implementation of std::vector contains 2 pointers:
The beginning of the allocated array
1 element after the end of the allocated array
Essentially, when you declare a vector it has no space allocated in the heap, but as you add elements this changes.
Note that std::vector manages the memory it uses, so there is no need for you to worry about new and delete (unnecessary complexity). As soon as it goes out of scope, it deallocates its memory (stack and heap).
As you said, a vector can be passed very easily by reference, which works the same way as a pointer for machine code, and it's more clear.

Why does a vector have to move its data members when reallocating

Assuming that a vector contains an array internally of std::aligned_storage instances that actually contain elements of the type the vector is templated on if the aligned_storage instance is in use.
When the vector has to allocate a new block of memory and move all its elements, why does it invoke the move constructor of each element in use and then destroy the old element? Why not just copy over all the bytes byte by byte and just delete the old array without calling destructors? This would make the new array an exact copy of the old array without the overhead of moving and destroying elements.
Maybe I'm a little tired and am missing something really basic. But I cannot think of a reason why this would not work.
It would not be safe to merely copy the bytes. Imagine, for example, that your object has two members, p and d, and p is a pointer that points to d. If you just copy the bytes, you'd copy the value of p that points to the old location of d, which has been destroyed.
This is a simple example, but in general, the reason for C++ constructors, destructors, copy and move constructors, is to allow your object to be "smarter" than just a sequence of bytes would be. Member variables have meaning, and that meaning is understood by your code, not by the compiler.

Run time fault is coming if allocation memory using malloc to store STL list [duplicate]

This question already has an answer here:
allocating space to list<int> pointers using malloc not working
(1 answer)
Closed 5 years ago.
I want to create array of list which can store list. so i use malloc and get the storage.
list<int>*adj;
adj = (list<int>*)malloc(sizeof(list<int>)*v);
adj[0].push_back(1); ==> crash occure in this line...
But when is use new operator then it works fine..
list<int> *adj;
adj = new list<int>[v];
adj[0].push_back(1); ==> works fine
Can somebody help why malloc is not working ?
Main difference btw allocating memory by malloc() and operator new - malloc() would not call constructor and so your object is not initialized properly. You should not use malloc() to create c++ objects unless you have real reason, if you do have one use placement new to initialize object properly.
malloc only returns a pointer to bytes of uninitialized memory it allocated. That means that you do not actually have a std::list object (nothing ever constructed one since malloc has no notion of such concepts), but merely a pointer to enough bytes of memory to store a std::list object in.
This is different to the line with new: new allocates enough memory for a std::list object and then actually constructs one in this memory. After this construction, you can use the std::list, and this construction is required for std::list to work!
You should not use malloc in C++, at least I do not know a single valid usecase for it.
malloc is C function. It ONLY allocates sizeof memory. You should use new operator, which will also call list constructor.
Probably list constructor also calls new to allocate some internal data, without calling it you have pointer to corrupted structure.

About constructors/destructors and new/delete operators in C++ for custom objects

Suppose I have a Linked List I created myself. It has its own destructor, which frees the memory. This Linked List does not overload new or delete.
Now, I'm trying to create an array of said linked lists (open hashing, if I understand correctly). Then I allocate the necessary memory inside the constructor of this open hashing class. The new operator being called inside the constructor is enough to correctly allocate the memory for the array, right? I'm not sure because I haven't overloaded new for the Linked List class.
Also, assuming my array of Linked Lists is called elements, could I just write "delete[] elements" in the destructor? Would that call the destructor for each element in the array and correctly free the memory?
Finally, if both my assumptions are correct (ie, I don't have to overload new and delete to use them with my custom class), what is the point of overloading such operators?
Yeah you are right. A plain
elements = new LinkedList[N];
is enough to allocate them. You can then access them
elements[i]->push(....);
and delete them in your destructor using the way you showed:
delete[] elements;
The compiler will remember how many elements were allocated, and call the destructor for each list correctly. The point of overloading the new and delete operator is to provide custom memory allocation strategy. For example, you could preallocate memory, and then take from that pool, instead of allocating everytime again memory from the OS.
But note, you have to write a copy constructor and copy assignment operator too. Since if someone copies your hash map, the linked list has to be copied too, and not just the pointer. Or you can make the copy constructor and copy assignment operator private and don't define them, disallowing copies of your hash map:
....
private:
MyHashMap(MyHashMap const& rhs);
MyHashMap & operator=(MyHashMap const& rhs);
....
The new operator does two things: allocating memory and calling the constructor.
The delete operator calls the destructor and then frees the memory.
Arrays created with new [] must be destroyed with delete[].
You generally don't need to overload new or delete except for performance reasons. You might have a predictable pattern of allocation/deallocation which makes a particular allocation strategy very suitable (fast or low memory use).
You may wish to have a look at this page.
All of your assumptions are correct.
There are lots of uses for overloading new and delete, but it is not done often. One common reason is for tracking memory allocations in order to spot memory leaks. A lot of compile time leak trackers do this, but have sort of become obsolete with better external apps like valgrind. You can also do things like use pooled memory.