When a vector becomes full it is reallocated and all of it iterators and pointers to elements are invalidated. Does this behaviour change in any way when the vector is created with new?
std::vector<int>* v = new std::vector<int>(); //What happens if this vector gets reallocated?
And can I get the object from its pointer (as a separate variable), or do I have to copy it to another object?
As long as v is not destroyed, the underlying array (wrapped inside by the std::vector class template ) is in good state, irrespective of any reallocation.
To answer the title question: yes, it's safe (if unusual) to allocate a std::vector object dynamically.
To answer the body question:
How the std::vector object itself is allocated does not affect the validity of its iterators etc. at all. They still become invalidated by reallocation of the std::vector's internal data store.
For the final question, I don't quite understand. *v will give you a reference to the dynamically allocated vector. It does not copy anything. (*v)[3] will give you the int on index 3 in the vector, for example.
It doesn't matter whether you create the vector on the stack or on the heap. The vector actually owns the storage space which is probably just an array that it allocates and reallocates. The pointer you have is to the owner which doesn't change. The only difference with newing it is that you are responsible for releasing the owner (presumably the owner releases the owned memory).
Using new is safe, but doesn't help the problem you have with dynamic reallocation. The vector object promises continuity of the storage space, so there is not much you can do. After certain operations, you may not rely on iterators anymore. To prevent dynamic reallocation at unknown times use reserve() or resize() explicitly.
Related
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.
We have a scenario where we need to create an
std::vector<std::vector<float>> data;
because the vectors aren't at all the same length.
When data gets freed, does every vector inside data also free up its space?
All of the standard library types implement RAII appropriately. That is, any kind of internal dynamic allocation that they perform will be cleaned up automatically by the time the object is destroyed. You never need to worry about it.
In the case of the standard containers, like std::vector, it will automatically ensure that each of its elements is destroyed. Of course, if the elements of the std::vector are themselves std::vectors, they will in turn destroy their elements. Everything is automatic.
You may have seen examples in which you have a std::vector<T*> and the T objects were then allocated manually using new. It's important to realise here that the elements of the vector are not the T objects, but T* objects. The pointers will be cleaned up automatically. Since you manually allocated the T objects, you need to manually deallocate them. (As #Veritas says in the comments, in this case you should prefer using smart pointers)
Yes
Whenever The "Scope" of 'data' ends , The destructor will be automatically called and memory that was allocated for'data' will be freed.
Whenever the destructor is called for a vector then the destructor each of its elements will be called.
Suppose for vector a(5)
Here destructors of a[0],a[1],... will be called.
Similarly in the above case vector< vector > x;
destructors of x[0],x[1] will be called consecutively..
But here each element x[i] is again a vector so again destructors of x[i][0],x[i][1]... will be called..
In this way all elements are destroyed Recursively..
I just wonder what's wrong with vector of pointer. some of my friend recommend me to use list instead of vector. will this cause a problem:
vector<Fruit*> basket;
basket.push_back(new Apple());
basket.push_back(new Orange());
vector<Fruit*> temp;
temp.push_back(basket[1]);
If I delete vector temp, do I destroy the basket[1] object too? if not, what's the problem with using vector of pointer?
If I delete vector temp, do I destroy the basket[1] object too?
No. First of all, you cannot delete temp; rather, it will get destroyed when going out of scope. And when this happens, the objects pointed by elements of the vector won't be automatically deleted.
This is, however, not a specific problem of vector: using list will not save you from this issue. The problem is rather with raw pointers. If you want the pointed objects to be automatically deallocated when the the lifetime of the last pointer which points to it ends, you should use smart pointers.
Depending on the ownership policy that your application needs, you might choose between shared_ptr and unique_ptr. The caveat with shared_ptr is that referencing cycles shall be avoided, to prevent mutually referencing objects from keeping each other alive. You may want to check weak_ptr in this respect.
Finally, unless you have a good reason for not using vector, vector should be the default choice for a container. From Paragraph 23.2.3/2 of the C++11 Standard:
The sequence containers offer the programmer different complexity trade-offs and should be used accordingly. vector or array is the type of sequence container that should be used by default. list or forward_list should be used when there are frequent insertions and deletions from the middle of the sequence. deque is the data structure of choice when most insertions and deletions take place at the beginning or at the end of the sequence.
If either of the vectors, basket or temp, are destroyed none of the Fruits are destroyed. Anything that is dynamically allocated with new must be deleted. When the vectors go out of scope, they do not delete the objects that are pointed to by their elements. If you delete an object through one vector that is pointed to in the other vector, both point at the now deleted object.
Since your vectors have automatic storage duration, you definitely must not do delete basket; or delete temp;.
It's not recommended to use raw pointers in general, especially with dynamically allocated storage that you may forget to delete. In this case, however, you do need polymorphic behaviour, which is provided by pointers. You should use a smart pointer to avoid the problems with raw pointers. Try a std::vector<std::shared_ptr<Fruit>>.
I am using vector as a buffer to store some objects to be later appended to another vector.
std::vector<Link*> buffer_vector;
std::vector<Link*> main_vector;
main_vector.insert(main_vector.end(),buffer_vector.begin(),buffer_vector.end());
The process of filling the buffer and appending occurs repeatedly. Therefore I need to clear the buffer at every iteration. My concern is if I use .erase or .clear methods to clear the buffer, the objects in the main vector will be deleted. Is this assumption correct?
If yes, is there a workaround for that?
Thank you
vahid
Your concern is incorrect.
main_vector.insert(main_vector.end(),buffer_vector.begin(),buffer_vector.end()); copies the elements from buffer_vector into main_vector.
These copied elements are totally separate from the original elements, and so they are not affected by modifications to the elements that they were copied from.
If you mean clearing the buffer_vector will clear the contents in main_vector, no they are separate copies.
Insertion into a vector is done by copy. In other words, you're pushing a copy of the element into the new vector. A different copy will be deleted when the buffer vector is cleared.
(This assumes that you're pushing the same type into both vectors, and not something like a pointer to an element to a vector in the first vector into the second vector.)
You are copying the elements into the vector, and they will stay there until you delete them.
In the code you show, you are storing pointers into objects. The pointers will be copied, and nothing will happen to the allocated memory when the original vector is cleared or the elements erased.
Actually nothing will happen to the pointed memory when the second vector goes out of scope!! Your program leaks memory, you need to manually manage the pointers or else choose an appropriate smart pointer that you can use inside a vector (consider std::unique_ptr or std::shared_ptr from C++11 or the equivalents from boost or TR1).
You may be confused about how a vector manages its objects. When you push_back into a vector, you make a copy. When you push_back a pointer, it copies the pointer. When you call clear() or erase() it deletes the pointer but not the object the pointer points to.
I am assuming you new'ed all your Link objects and added them to the vector container. You will need to delete them yourself, the container will not destroy the pointed to object for you (even if the container itself is destroyed when it goes out of scope). If you clear() both your containers before calling delete on all your Link objects, you will cause a memory leak (assuming you are not keeping pointers to Link objects somewhere else).
I am having some difficulty understanding how containers are implemented in C++. Specifically, how can I deal with data allocated on the stack vs data allocated on the heap. For instance:
vector<int> VectorA;
VectorA.push_back (1);
VectorA.push_back (2);
VectorA.push_back (3);
vector<int*> VectorB;
VectorB.push_back (new int (1));
VectorB.push_back (new int (2));
VectorB.push_back (new int (3));
How does one deal with making sure the integers in VectorB are deleted properly. I remember reading somewhere that std::vector only calls the destructor and doesn't actually delete anything. Also, if I wanted to implement my own LinkedList class, how would I deal with this particular problem?
The ideal way to deal with the problem is by using Smart Pointers as elements of your container instead of raw pointers.
Otherwise you have to manually do the memory management yourself.
The objects stored in the vector are stored on the heap anyway (in space allocated by the vector).
There is very little advantage in allocating the objects separately (option B), unless you intend to manage them somehow outside of the vector. In that case the vector can just destroy the pointers it stores, and trust the real owner to destroy the objects themselves.
The short answer is that most don't deal with such things at all. The standard containers (e.g., std::vector) don't store the original object at all -- they store a copy of the object. They manage the storage for their own copy, and it's up to you to manage the storage for the original.
In the case of storing pointers, you're basically taking responsibility for managing the storage pointed to by the pointer. The container is still making (and managing the storage for) a copy, but it's just a copy of the pointer, not the object to which it refers. That's up to you to deal with.