Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an empty vector call the value type's default constructor?

Using g++, I observe that creating a vector of size zero calls the vector's parameterized object type's constructor once. It then is deleted. Why does this happen?

#include <iostream> #include <vector> using namespace std;  class s {     public:     s() { cout << endl << "default s constructor" << endl; }     ~s() { cout << endl << "default s destructor" << endl; }  };  int main() {     vector<s> v(0); } 

Output:

default s constructor

default s destructor

like image 605
torahmike Avatar asked Jun 27 '11 03:06

torahmike


People also ask

Does vector require default constructor?

Every time it appears as if std::vector "requires" a default constructor from you, it simply means that somewhere you relied on a default argument of some of the vector s methods, i.e. it was you who tried to default-construct an element, not the vector.

Why is it called a default constructor?

A default constructor is a constructor that either has no parameters, or if it has parameters, all the parameters have default values. If no user-defined constructor exists for a class A and one is needed, the compiler implicitly declares a default parameterless constructor A::A() .

Can a default constructor be empty?

Providing an empty default constructor( private ) is necessary in those cases when you don't want an object of the class in the whole program. For e.g. the class given below will have a compiler generated default empty constructor as a public member . As a result, you can make an object of such a class.

Who calls the default constructor?

It is a special type of method which is used to initialize the object. Every time an object is created using the new() keyword, at least one constructor is called. It calls a default constructor if there is no constructor available in the class. In such case, Java compiler provides a default constructor by default.


2 Answers

Because you're explicitly passing an initial size, which calls a constructor that has another parameter whose default value is s(). Just leave out the (0) (i.e. std::vector<s> v;) and it won't happen.

For completeness, the Standard 23.2.4-2 defines the constructor you're calling as:

    explicit vector(size_type n, const T& value =T(),
                                    const Allocator& = Allocator());

Aside (relevant to C++03 but not C++11)

Another interesting behavioural aspect of this constructor also raises its head on S.O. periodically: when the initial number of elements requested is > 0, it copy-constructs those elements from the prototypal parameter to the constructor:

  • people often put a default constructor that leaves member variables uninitialised, hoping to make vector(n) almost as fast as the underlying free store allocation, BUT
  • the copy-constructor is still called n times to copy the "garbage" content of the prototypal object into each of the requested elements

This has an obvious performance cost, but can also crash the application if the garbage content includes e.g. pointers that the copy-constructor can only assume are valid. Similarly, it's extremely dangerous to even push_back such an uninitialised garbage object - it lacks proper value semantic encapsulation and may be copied as the vector resizes, algorithmic operations like std::sort() are performed on the vector etc..

like image 86
Tony Delroy Avatar answered Sep 21 '22 09:09

Tony Delroy


The actual constructor you are calling is (from cplusplus.com):

explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() ); 

So even though you only specify the size, a new T object is created for second parameter, and will therefore also be destroyed at the conclusion of the constructor.

like image 31
Ken Wayne VanderLinde Avatar answered Sep 21 '22 09:09

Ken Wayne VanderLinde