31

I have some simple function that uses vector like this (pseudo code):

void someFunc(void) {

    std::vector<std::string> contentVector;

    // here are some operations on the vector

    // should I call the clear() here or this could be ommited ?
    contentVector.clear();

}

Should I call the clear() or this could be ommited ?

Michal Przybylowicz
  • 1,558
  • 3
  • 16
  • 22
  • 2
    The destructor will handle the cleanup. :) – Borgleader Feb 05 '14 at 03:30
  • It is better than could, it should be omitted !! That is all the point of the destructor and of the RAII. Let the destructor handle the cleaning, you have nothing do to. It is great, isn't it ? – Davidbrcz Feb 05 '14 at 10:28
  • 1
    This question demonstrates C++'s killer feature: RAII. In a well-designed object, the object's resources are tied to the object's lifetime, and this is supported explicitly within the language. – Kaz Dragon Feb 05 '14 at 10:28

5 Answers5

31

If we look at the cppreference.com entry for std::vector::~vector it says:

Destructs the container. The destructors of the elements are called and the used storage is deallocated. Note, that if the elements are pointers, the pointed-to objects are not destroyed.

so no you don't have to call clear.

If we want to go to the draft standard, we have to look at section 23.2.1 General container requirements paragraph 4 which says:

In Tables 96 and 97, X denotes a container class containing objects of type T, a and b denote values of type X,[...]

and then look at Table 96 — Container requirements which has the following expression entry:

(&a)->~X()  

and the following note:

note: the destructor is applied to every element of a; all the memory is deallocated.

Update

This is RAII in action and as Bjarne Stroustrup says in Why doesn't C++ provide a "finally" construct?:

Because C++ supports an alternative that is almost always better: The "resource acquisition is initialization" technique (TC++PL3 section 14.4). The basic idea is to represent a resource by a local object, so that the local object's destructor will release the resource. That way, the programmer cannot forget to release the resource.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
17

There is absolutely no need to do that. std::vector and all other containers automatically destroys their elements when they themselves would be destroyed. That means that their destructors are responsible for that action. So, don't.

The beauty of this is that containers are naturally exception safe[1]:

void someFunc(void) {

    std::vector<std::string> contentVector;

    // here are some operations on the vector

    throw std::runtime_error("I just want to throw!");

    contentVector.clear();
}

Will the line contentVector.clear(); be called? No. But you're still safe because it is guaranteed that contentVector's destructor will be called.

From vector[2]:

Destructs the container. The destructors of the elements are called and the used storage is deallocated. Note, that if the elements are pointers, the pointed-to objects are not destroyed.


[1] You still need to make your elements exception safe though (have them properly free their resources whenever their destructors are called).

[2] See comments below for some thoughts on the SGI STL docs.

ALOToverflow
  • 2,679
  • 5
  • 36
  • 70
Mark Garcia
  • 17,424
  • 4
  • 58
  • 94
  • 1
    SGI is not a definitive reference. Just sayin' since I'm sure it's correct in this case. – Mark Ransom Feb 05 '14 at 03:44
  • @MarkRansom One links cppreference, another cplusplus.com, me then... `;)`. The SGI STL website sure is a good, if not definitive, resource. The OP will sure have something to learn from this "classic" site. – Mark Garcia Feb 05 '14 at 03:48
  • 2
    The problem is that SGI does not document the official standard, it documents the precursor to it. There are some subtle and not-so-subtle differences. See http://stackoverflow.com/questions/5266386/what-are-the-specific-differences-between-the-original-stl-and-those-parts-of-it – Mark Ransom Feb 05 '14 at 03:54
  • @MarkRansom I know. But it is good to know that it has the same behavior in this case even if it is the precursor to the standard library, which means that you can still rely on the behavior/guarantee for older compilers. – Mark Garcia Feb 05 '14 at 03:56
5

No need, it will get cleared automatically once it is out of scope i.e destructor will destroy the container object.

Varo
  • 831
  • 1
  • 7
  • 16
1

You can omit using the .clear() function because vector's destructor runs once contentVector goes out of scope at the '}'.

This deallocates the memory that stores vector's data.

DaBuj
  • 183
  • 1
  • 2
  • 5
  • The community consensus [is that cplusplus.com is not a good reference](http://meta.stackexchange.com/questions/194788/links-being-changed-to-cppreference-com). – Shafik Yaghmour Feb 05 '14 at 16:23
1

Since I don't think anyone else has mentioned this, but if your vector was

std::vector<std::string*> vector;

you should free the memory allocated to each element before the function finishes (unless you've passed ownership to somewhere else - such as a global variable etc)

for (auto i : vector) {
  delete i;
}
Michael
  • 979
  • 6
  • 13
  • 3
    These days, with C++11 becoming reasonably common, you probably should be using `std::unique_ptr` instead of `std::string*` so that the machinery takes care of this as well. And since your foreach loop indicates C++11 being used, that's the way I'd go. By the way, this is one aspect of what this footnote 1 in [Mark's answer](http://stackoverflow.com/a/21568114/1468366) is talking about. – MvG Feb 05 '14 at 10:28
  • I wrote the auto part because I was too lazy to write out the full version without vim macros. If you have c++11 or boost, then yes. but a pointers destructor *does not* free the memory (and obviously can't be changed) – Michael Feb 05 '14 at 10:32