Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is it that we're allowed to create a const std::vector without any initializer unlike normal const objects

I am learning about std::vector in C++. I learnt that a const std::vector<int> means that we cannot change the individual elements within that vector and also cannot append/push_back more elements into it i.e., we only have read-access to the elements, which is expected from an entity that is a const. But i find a difference when defining a const std::vector than defining other const types like int, double etc. The situation is shown below:

int main()
{
    const int i;   //doesn't compiler as expected: initializer needed here 
    const std::vector<int> vec1 ;  //COMPILES FINE: WHY ISN'T AN INITIALIZER NEEDED HERE?

}

As we can see that for a const built in type(like int), we must provide an initializer.

My first question is that why isn't this the case for std::vector. That is, how(why) are we allowed to omit the initializer for a const vector. I mean the const vector means that we won't be able to add elements into it so it seems that this vec1 is useless(practically) now.

So my second question is that is there a use for vec1 ? I mean since the standard allows this so they may have already thought about this case and found out that this vec1 can be useful somewhere. That is, what are the use cases for this vec1 that had no initializer at the time of its definition.

like image 870
Anoop Rana Avatar asked Sep 15 '25 22:09

Anoop Rana


1 Answers

As we can see that for a const built in type(like int), we must provide an initializer.

That is incorrect. You must ensure that a const object is initialized.

If you do not provide an initializer for an object, that object will undergo the process of default initialization:

To default-initialize an object of type T means:

  • If T is a (possibly cv-qualified) class type ([class]), constructors are considered. The applicable constructors are enumerated ([over.match.ctor]), and the best one for the initializer () is chosen through overload resolution ([over.match]). The constructor thus selected is called, with an empty argument list, to initialize the object.
  • If T is an array type, each element is default-initialized.
  • Otherwise, no initialization is performed.

vector<int> is a class type, so the first option is used. The default constructor will be called to initialize it.

int is not a class type. It is also not an array type. Therefore, no initialization is performed. And if this happens to a const object, the code is ill-formed.

For initializing const object, further rules exist:

If a program calls for the default-initialization of an object of a const-qualified type T, T shall be a const-default-constructible class type or array thereof.

int is not a class type or array of class types at all. So any attempt to create a const-qualified object of type int with default-initialization violates this rule and is ill-formed.

vector<int> happens to follow the rules of const-default-constructible, which is why your code works.

As to whether this particular object is "useful", that's up to you. It's an empty vector<int> which cannot be made non-empty. If that's useful to you in some circumstance, then it is useful.

like image 91
Nicol Bolas Avatar answered Sep 18 '25 17:09

Nicol Bolas