C++ delete vector, objects, free memory
Asked Answered
A

7

73

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();
Arezzo answered 5/5, 2012 at 18:55 Comment(2)
There is nothing different from the second case than the first case other than the fact it points a vector. I think this question should be broadened so that you get a grasp on how memory allocation / deallocation should work, and probably pointers too.Flexure
This one says declaring it inside a function stack automatically calls the destructor at closure. #3055067Lillis
H
109

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.

Honeysucker answered 5/5, 2012 at 18:59 Comment(8)
Hey thanks for the reply. do you mind explaining what the above does? after calling that, do i need to call clear?Arezzo
@dupdupdup: No, you don not need to call clear. The objects that were in tempVector are transfered to the empty vector. Then, the empty vector, since it is a nameless temporary object, is destroyed, and its contents, which were previously owned by tempVector, are destroyed and the memory deallocated.Honeysucker
I'm no C++ expert, mind explaining how this is better than the tempVector.resize(0) I'd try first?Extensible
std::vector::resize is not required to release memory, it's perfectly allowed to keep it around in case it's needed later.Spiegelman
@delnan: I wouldn't call it better, but it achieves the goal of deallocating the memory, whereas resize(0) does not. (that would do the same thing as clear())Honeysucker
@Useless: I thought resize is required to keep the memory. Am I wrong on that?Confucianism
I think resize and clear are both described in terms of the number of elements, and it's not clear any requirements are placed on the amount of underlying storage kept, except that it be at least sufficient for the requested number of elements.Spiegelman
wouldn't simple assignment do the same? tempVector = vector<tempObject>();Timikatiming
S
34

There are two separate things here:

  1. object lifetime
  2. 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.

Spiegelman answered 5/5, 2012 at 19:8 Comment(3)
What do you mean by 'If you decide to push.. this saves time as it can reuse the old memory.'? Why does old memory matter when you want to add new items?Boudoir
The vector has to manage storage internally for the objects it stores. Creating a new vector requires allocating new storage, but clearing & reusing an existing vector allows (but doesn't guarantee) reuse of its already-allocated storage.Spiegelman
@Spiegelman Why do you need to delete a pointer always? "If you used vecPtr = &vec;, and if vec is an auto variable, which used automatic memory, or vec is a static variable or global variable, which used static memory, you should not delete it, it will be deallocated automatically. Only dynamic memory could be deleted."Gilkey
H
20

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.

Hyksos answered 5/5, 2012 at 19:3 Comment(0)
M
10

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.

Mandrel answered 31/7, 2020 at 17:27 Comment(3)
Hi.. Just a quick question, if I allocate the memory using 'new'. Can I still use your answer to deallocate the memory instead of 'delete'.Marchesa
+1 for the readability. It's amazing how was the "fancy" swap() method dominating the search results ...Skyway
Appreciate the readability of this over the swap method. +1Veronique
W
7

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
Wintry answered 10/8, 2019 at 14:20 Comment(0)
S
2

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();
Sharpie answered 10/9, 2020 at 13:9 Comment(0)
M
0

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.

Meritocracy answered 6/6, 2017 at 19:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.