The first solution is:
std::vector<int> *vec = new std::vector<int>;
assert(vec != NULL);
// ...
delete vec;
An alternative is:
std::vector<int> v;
//...
vec.clear();
vec.swap(std::vector<int>(vec));
The second solution's a bit of a trick --- what's the "right" way to do it?
Update:
I'm aware that the destructor will be called once it's off the stack, I was curious about other methods.
The simplest and most reliable way to deallocate a vector is to declare it on the stack and simply do nothing.
void Foo() {
std::vector<int> v;
...
}
C++ guarantees that the destructor of v will be called when the method executes. The destructor of std::vector will ensure any memory it allocated is freed. As long as the T type of the vector<T> has proper C++ deallocation semantics all will be well.
The simplest way to deallocate all the storage in a vector, without destroying the vector object itself, is
vec = std::vector<int>();
Your second variant will have the same effect, but it jumps through more hoops on the way. The "copy and swap" trick deallocates any extra capacity in the vector, and can be useful if it contains some data you want to keep. If there's no data, then there's no need for copying or swapping.
std::vector<int> vi;
/*push lots of stuff into the vector*/
// clean it up in C++03
// no need to clear() first
std::vector<int>().swap(vi);
// clean it up in C++0x
// not a one liner, but much more idiomatic
vi.clear();
vi.shrink_to_fit();
I agree with Mike Seymour
try this then you will notice that the last is working fine
const int big_size = 10000;
vector<double> v( big_size );
cout << "Before clearing, the capacity of the vector is "
<< v.capacity() << " and its size is " << v.size();
v.clear();
cout << "\nAfter clearing, the capacity of the vector is "
<< v.capacity() << " and its size is " << v.size();
vector<double>().swap( v );
cout << "\nAfter swapping, the capacity of the vector is "
<< v.capacity() << " and its size is " << v.size();
vector<double> v1( big_size );
v1 = vector<double>();
cout << "\n After vector<double>();, the capacity of the vector is "
<< v1.capacity() << " and its size is " << v1.size();
My guess here is that you have a vector which temporarily contains a large amount of data. Once the vector has been cleared, it will still take up all of this memory. You want to release this memory after you are done with it, but you the function/object you are working with has not finished.
Solutions in decreasing order of desirability:
Rework the code so that the vector using code is in it's own block/function/object so that it will be destroyed naturally
Use the swap trick, this way you don't have to worry about making sure that the vector is deallocated in all circumstances. It's lifetime will be tied to the object/function you are in.
new/delete the vector. This will free up a little bit more memory then the previous method but is also harder to make sure no memory is leaked.
The only technical difference between swapping and deleting is the base vector itself is not destroyed. This is a small overhead and is not worth worrying about (as long as you do eventually destroy the vector)
The larger consideration is which makes it easier to write correct code, and I believe swap wins over deleting there, but is worse then moving the vector somewhere else.
Don't use memory allocation functions unless you really need to. If your class needs a vector, always, just ad the std::vector member directly. No need to do memory allocation here.
In the cases where you need the dynamic vector, allocating and deleting it like in your first example is 100% correct.
In the second example, the call to std::swap is strictly spoken not needed, because the clear method will clear the vector, making it empty. One possible problem is that there is no guarantee that the vector will actually free the memory, giving it back to the operating system (or to the run time). The vector might keep the allocated memory just in case you will fill the vector right after clearing it. The call to std::swap may be a trick to 'force' the vector to free its internal data, but there is no guarantee that this will actually happen.
Delete deallocates the memory, the memory is then free for the next object but the vector has gone.
The 2nd trick frees any excess memory but leaves the vector intact, but empty.
Although both appear to work, I see no reason not to just call delete on the pointer. The vector should have a destructor that is called that will handle everything else.
If you just let the vector go out of scope, it will clean itself up appropriately with no extra work. If the vector is a member variable of a class, and you want it to deallocate its contents before its owner is destructed, then just call vec.clear().
If you want to keep the vector but deallocate the memory that holds its contents, then vec.swap(std::vector<int>()); will do that. There's no need to copy-construct the temporary into the original unless vec contains items that you want to keep and you just want to shrink the allocated memory down to something close to the current size().
This is not a valid comparison because the examples are dealing with different kinds of objects: dynamic duration and local duration. You can call the destructor OR use the swap trick (aka shrink_to_fit) with either one. The right way depends on whether you need the vector object to persist or not.
For example, you may need it to persist if there are references or pointers to it that must remain valid, in which case shrinking is the only way, regardless of how it was allocated.
I'm not sure why your second example uses a copy constructor for the temporary rather than a default constructor. That would save you the .clear() line of code.
You could make this generic for any object, even if it's not a container. I'm assuming here that std::swap is specialized to call vector::swap.
template<typename T>
void ResetToDefault(T & value)
{
std::swap(T(), value);
}
std::vector<int> vec;
//...
ResetToDefault(vec);
In the case that the vector really needs to be on the heap don't forget about:
std::auto_ptr<std::vector<int> > vec(new std::vector<int>);
especially useful with code like:
std::auto_ptr<std::vector<int> > vec(vectorFactoryFunction());
Related
I have a unique_ptr pointing to a heap allocated vector, that itself stores pointers to dynamically allocated objects. The problem is I think the unique_ptr frees the dynamically allocated vector itself, but this vector's destructor doesn't free the dynamically allocated objects. So, how to solve this problem without changing the implementation of the program? I know if I used a shared_ptr I can use a custom destructor to free up storage, but I have to stick with unique_ptr for specific reasons.
So, can the vector have a custom destructor like shared_ptr has, that can free the stored objects?
std::unique_ptr<vector<Test*>>
You have a misunderstanding about how types work in C++. Every type has a fixed size. You can get this size with sizeof. For example, on a typical platform, a vector<Test*> has a size of 24 bytes.
When you allocate a vector on the stack, you are only allocating those 24 bytes on the stack. When you add objects to the vector, the vector will allocate memory from the heap to store those objects.
like I said I have to stick with this implementation since it save more stack memory than storing vector on the stack.
It won't. So you don't have to stick with this implementation. Switch to a sensible one such as std::vector<std::unique_ptr<Test>>.
And I dont want objects to be copied or moved to prevent moving objects and keeping hollow ones that take more space
A sensible implementation (such as std::vector<std::unique_ptr<Test>>) won't move the underlying objects. Move semantics for std::vector are already optimal on any sensible platform.
You are expecting moving a std::unique_ptr to be significantly different from moving a std::vector. Your reasoning for that assumption is faulty and, even if it was correct, this would still be a pointless increase in complexity.
In fact, why not just use vector<Test>?
Check this out:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> a;
for (int i = 0; i < 10; ++i)
a.push_back(i);
std::cout << &a[0] << std::endl;
std::vector<int> b = std::move(a);
std::cout << &b[0] << std::endl;
}
Output:
0x563caf0f1f20
0x563caf0f1f20
Notice that moving the vector didn't even move the objects in the vector. It just transferred ownership of the objects from one vector to the other.
Stop trying to optimize things that are already optimized.
For testing purposes, I was trying to create my own vector class, and I couldn't figure out how std::vector size reduction works.
class A
{
A()
{ std::cout << "A constructed") << std::endl; }
~A()
{ std::cout << "A destroyed") << std::endl; }
}
main()
{
std::vector<A> vec(3, A());
vec.resize(2);
std::cout << "vector resized" << std::endl;
}
Output is
A constructed (1)
A constructed (2)
A constructed (3)
A destroyed (1)
Vector resized
A destroyed (2)
A destroyed (3)
When vec.resize(2) is called, the third element is destroyed, but the vector's capacity is still 3. Then when vec is destroyed, all of its elements including the one already destroyed should be destroyed. How does std::vector know that he has already destroyed that element? How can I implement that in my vector class?
There's a difference between capacity and size. Given a std::vector<T> v; The vector has allocated memory for v.capacity() elements. But only in the first v.size() places contain constructed T objects.
So, v.reserve(1000) on an empty vector won't call any additional constructors. vec.resize(2) in your example destroys the last element and vec[2] is now an empty place in memory, but memory still owned by the vec.
I think your allocation looks like buffer = new T[newSize];. That is not how std::vector works which would not allow Ts that do not have default constructors. Maybe you did not realize this, but whenever you obtain a piece of memory, it already contains objects, let it be T x; or even new double[newSize]; which returns an array of doubles (although their constructors are empty).
There is only one way to get usable uninitialized memory in C++, which is to allocate chars. This is due to the strict aliasing rule. There also (is|must be) a way how to call a constructor explicitly on this memory i.e. how to create an object there. The vector uses something called placement new which does precisely that. The allocation is then simply buffer = new char[newSize*sizeof(T)]; which creates no objects whatsoever.
The lifetime of the objects is managed by this placement new operator and explicit calls to destructors.
emplace_back(arg1,arg2) could be implemented as {new(buffer + size) T(arg1,arg2);++size;}. Note that simply doing buffer[size]=T(arg1,arg2); is incorrect and UB. operator= expects that the left size(*this) already exists.
If you want to destroy an object with e.g. pop_back, you must do
buffer[size].~T();--size;. This is one of the very few places where you should call the destructor explicitly.
The simple answer is that vector internally manages constructor and destructor calls, often by using inplace operator new and operator delete methods.
Having popped an element, it is immediately descructed, and while the memory is still available, and may still contain some remnant values, std::vector itself knows which elements still need to be deleted, and won't call the destructor again.
When vec.resize(2) is called, the third element is destroyed, but the vector's capacity is still 3.
Yes. The capacity is how many elements the vector's internal array can physically hold. The size is how many elements in that array are actually valid. Shrinking the size does not affect the capacity at all.
Then when vec is destroyed, all of its elements including the one already destroyed should be destroyed.
The 3rd element that was previously destroyed and removed from the array is not destroyed again. Only size number of elements are destroyed, not capacity number of elements, like you are thinking.
How does std::vector know that he has already destroyed that element?
It tracks the size and capacity separately. When an element is removed from the array, the elements that follow it are moved down the array by 1 slot each, and the size is decremented.
I want to make a vector of objects, but I don't want to allocate them on the heap. I want to allocate them onto stack memory. But I'm running into issues.
struct Object { int x; Object(int x) { this->x = x; } };
int main() {
std::vector<Object*> v;
for (int i = 0; i < 5; i++) {
Object o (i);
v.push_back(&o);
std::cout << &o << std::endl; // keeps printing the same mem address...
// ...implying that these are all the same object
}
}
I have a suspicion that the object is deleting itself after going out of scope after each iteration of the for-loop.
Now, I know that you can just do v.push_back(new Object(i)) for each iteration and it would work. However, I do not want these objects allocated onto the heap where I need to manually manage the memory.
You are basically correct that "object is [being destructed] after going out of scope". It's also confusing because of what you're printing. Based on how the compiler allocates the variables with "automatic storage duration" within the loop, the stack variable Object o always has the same address.
std::vector<Object*> v;
for (int i = 0; i < 5; i++) {
Object o (i);
v.push_back(&o);
// Variable o still exists on the stack
std::cout << &o << std::endl; // Prints the address of the automatic variable 'o'
}
// At this point, no objects exist; they all went out of scope
// every pointer in v is invalid, pointing to the "ghost" of a destoryed object.
I think the simpler approach you are looking for is to simply create a vector of objects.
std::vector<Object> v;
for (int i = 0; i < 5; i++) {
v.push_back(Object(i));
std::cout << &(v.back()) << std::endl; // Prints the address of the Object just added
}
That said, you should understand that the std::vector<Object> will manage your object lifetimes properly, destroying the objects when the vector itself goes out of scope. But the objects are actually stored on the free store. This is okay.
Here is the output from ideone when compiling and running with a vector of Objects:
0x8e66008
0x8e6601c
0x8e66030
0x8e66034
0x8e66050
If you really don't want to allocate them on the stack, but instead just want the memory managed, you really should take few hours to fill in some knowledge gaps.
In particular, picking up a good amount of knowledge on RAII is crucial to using C++ and C++11 effectively. I highly recommend The C++ Language Reference, 4th Edition. The 4th edition is important because it's very different from the the 3rd edition.
In it, it'll show you that will likely want to use std::vector<std::unique_ptr> for this particular problem, or to make Object a managed object itself (with move semantics implemented).
The vector is deleted, not the objects.
The following means that you save pointers in the vector v:
std::vector<Object*> v;
You could do this:
std::vector<Object> v;
in which case you get many objects, but then you get copies of your objects which at times is either not possible or not something you want (although newer version of the C++ compiler can do a move instead of a copy, but I don't think that would work in this case...)
Another way if you want the Objects to be allocated and then automatically deleted is to use a smart pointer.
#include <memory>
std::vector<std::shared_ptr<Object> > v;
In that case the Objects are allocated by you and freed whenever the vector gets deleted.
However, your problem is that you initialize objects on the stack and assign that stack pointer to your vector. I would image that your print shows you that the pointer is always the same... meaning that the previous object gets destroyed and a new one created on each iteration.
So I would replace these lines:
std::vector<Object*> v;
Object o (i);
v.push_back(&o);
By something like this:
std::vector<std::shared_ptr<Object> > v;
std::shared<Object> o(new Object(i));
v.push_back(o);
If you do not know anything about shared pointers, I suggest you read up on them. It's very useful whenever you allocate objects with new. Also there are a few traps with what is called circular references (i.e. check out weak_ptr as well). But in this way you do not have to manage memory and you have good pointers.
If you prefer the solution with the Object by itself, it would be something like this:
std::vector<Object> v;
Object o(i);
v.push_back(o);
This way you avoid the heap, however, you make copies each time you push_back (or a move). So if your objects are big, that's not a good idea.
Also, within your object, if you end up having pointers, using smart pointers will help you greatly too. So that's anyway a good idea to learn about them.
I am totally confused with regards to deleting things in C++. If I declare an array of objects and if I use the clear() member function. Can I be sure that the memory was released?
For example :
tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;
tempVector.pushback(obj1);
tempVector.pushback(obj2);
Can I safely call clear to free up all the memory? Or do I need to iterate through to delete one by one?
tempVector.clear();
If this scenario is changed to a pointer of objects, will the answer be the same as above?
vector<tempObject> *tempVector;
//push objects....
tempVector->clear();
You can call clear, and that will destroy all the objects, but that will not free the memory. Looping through the individual elements will not help either (what action would you even propose to take on the objects?) What you can do is this:
vector<tempObject>().swap(tempVector);
That will create an empty vector with no memory allocated and swap it with tempVector, effectively deallocating the memory.
C++11 also has the function shrink_to_fit, which you could call after the call to clear(), and it would theoretically shrink the capacity to fit the size (which is now 0). This is however, a non-binding request, and your implementation is free to ignore it.
There are two separate things here:
object lifetime
storage duration
For example:
{
vector<MyObject> v;
// do some stuff, push some objects onto v
v.clear(); // 1
// maybe do some more stuff
} // 2
At 1, you clear v: this destroys all the objects it was storing. Each gets its destructor called, if your wrote one, and anything owned by that MyObject is now released.
However, vector v has the right to keep the raw storage around in case you want it later.
If you decide to push some more things into it between 1 and 2, this saves time as it can reuse the old memory.
At 2, the vector v goes out of scope: any objects you pushed into it since 1 will be destroyed (as if you'd explicitly called clear again), but now the underlying storage is also released (v won't be around to reuse it any more).
If I change the example so v becomes a pointer to a dynamically-allocated vector, you need to explicitly delete it, as the pointer going out of scope at 2 doesn't do that for you. It's better to use something like std::unique_ptr in that case, but if you don't and v is leaked, the storage it allocated will be leaked as well. As above, you need to make sure v is deleted, and calling clear isn't sufficient.
vector::clear() does not free memory allocated by the vector to store objects; it calls destructors for the objects it holds.
For example, if the vector uses an array as a backing store and currently contains 10 elements, then calling clear() will call the destructor of each object in the array, but the backing array will not be deallocated, so there is still sizeof(T) * 10 bytes allocated to the vector (at least). size() will be 0, but size() returns the number of elements in the vector, not necessarily the size of the backing store.
As for your second question, anything you allocate with new you must deallocate with delete. You typically do not maintain a pointer to a vector for this reason. There is rarely (if ever) a good reason to do this and you prevent the vector from being cleaned up when it leaves scope. However, calling clear() will still act the same way regardless of how it was allocated.
if I use the clear() member function. Can I be sure that the memory was released?
No, the clear() member function destroys every object contained in the vector, but it leaves the capacity of the vector unchanged. It affects the vector's size, but not the capacity.
If you want to change the capacity of a vector, you can use the clear-and-minimize idiom, i.e., create a (temporary) empty vector and then swap both vectors.
You can easily see how each approach affects capacity. Consider the following function template that calls the clear() member function on the passed vector:
template<typename T>
auto clear(std::vector<T>& vec) {
vec.clear();
return vec.capacity();
}
Now, consider the function template empty_swap() that swaps the passed vector with an empty one:
template<typename T>
auto empty_swap(std::vector<T>& vec) {
std::vector<T>().swap(vec);
return vec.capacity();
}
Both function templates return the capacity of the vector at the moment of returning, then:
std::vector<double> v(1000), u(1000);
std::cout << clear(v) << '\n';
std::cout << empty_swap(u) << '\n';
outputs:
1000
0
Move semantics allows for a straightforward way to release memory, by simply applying the assignment (=) operator from an empty rvalue:
std::vector<int> vec(100, 0);
std::cout << vec.capacity(); // 100
vec = vector<int>(); // Same as "vector<int>().swap(vec)";
std::cout << vec.capacity(); // 0
It is as much efficient as the "swap()"-based method described in other answers (indeed, both are conceptually doing the same thing). When it comes to readability, however, the assignment version makes a better job.
You can free memory used by vector by this way:
//Removes all elements in vector
v.clear()
//Frees the memory which is not used by the vector
v.shrink_to_fit();
If you need to use the vector over and over again and your current code declares it repeatedly within your loop or on every function call, it is likely that you will run out of memory. I suggest that you declare it outside, pass them as pointers in your functions and use:
my_arr.resize()
This way, you keep using the same memory sequence for your vectors instead of requesting for new sequences every time.
Hope this helped.
Note: resizing it to different sizes may add random values. Pass an integer such as 0 to initialise them, if required.
I know that variables allocated on that stack of a function become inaccessible when the function finishes execution. However, vector types allocate their elements on the heap no matter how they are allocated. So for instance,
vector<int> A;
will allocate space for its elements on the heap instead of the stack.
My question is, assume I have the following code:
int main(int argc, char *argv[]) {
// initialize a vector
vector<int> A = initVector(100000);
// do something with the vector...
return 0;
}
// initialize the vector
vector<int> initVector(int size) {
vector<int> A (size); // initialize the vector "on the stack"
// fill the vector with a sequence of numbers...
int counter = 0;
for (vector<int>::iterator i = A.begin(); i != A.end(); i++) {
(*i) = counter++;
}
return A;
}
Will I have memory access problems when using the vector A in the main function? I tried this several times and they all worked normally, but I'm scared that this might just be luck.
The way I see it is, the vector A allocates its elements on the heap, but it has some "overhead" parameters (maybe the size of the vector) allocated on the stack itself. Therefore, using the vector in the main function might result in a memory access problem if these parameters are overwritten by another allocation. Any ideas?
When you do "return A;" you return by value, so you get a copy of the vector -- C++ creates a new instance and calls copy constructor or operator= on it. So in this case it doesn't matter where the memory was allocated as you have to copy it anyway and destroy the old copy (some possible optimizations notwithstanding).
The data in the vector (and all other STL containers) is moved around by value as well, so you store the copy of your integers, not pointers to them. That means your objects can be copied around several times in any container operation and they must implement a copy constructor and/or assignment operator correctly. C++ generates those for you by default (just calling copy ctor on all your member variables), but they don't always do the right thing.
If you want to store pointers in an STL container consider using shared pointer wrappers (std::shared_ptr or boost::shared_ptr). They will ensure the memory is handled correctly.
Yes, it will work normally because the memory for the elements are allocated and that is what will be used to build the vector<int> A = variable. However, performance wise, it is not the best idea.
I would suggest changing your function to be the following though
void initVector(vector<int>& a, int size)
For additional references on usage, please see Returning a STL vector from a function… and [C++] Returning Vector from Function.
For an additional reference on performance (using C++11), please see Proper way (move semantics) to return a std::vector from function calling in C++0x
C++ vector actually has two pieces of memory that are linked with a single pointer. The first one is in stack, and the 2nd one in heap. So you have features of both stack and heap in a single object.
std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
std::cout << sizeof(vec) << std::endl;
Once you run that code, you'll notice that the stack area does not contain the elements, but it still exists. So when you pass the vector from function to another, you'll need to manipulate the stack areas, and the vector will get copied like any other stack-based object.