Search code examples
c++vectorindexingstandard-librarypush-back

Why is it considered bad style to use the index operator on a vector in C++?


I am working on a program that uses vectors. So the first thing I did was declare my vector.

std::vector<double> x;
x.reserve(10)

(BTW, is this also considered bad practice? Should I just type std::vector<double> x(10)?)

Then I proceeded to assign values to the vector, and ask for its size.

for (int i=0; i<10; i++)
{
    x[i]=7.1;
}
std::cout<<x.size()<<std::endl;

I didn't know it would return 0, so after some searching I found out that I needed to use the push_back method instead of the index operator.

for (int i=0; i<10; i++)
{
    x.push_back(7.1);
}
std::cout<<x.size()<<std::endl;

And now it returns 10.

So what I want to know is why the index operator lets me access the value "stored" in vector x at a given index, but wont change its size. Also, why is this bad practice?


Solution

  • It sounds like you're asking why things are the way they are. Most of it is down to efficiency.

    If x[i] were to create value if it didn't already exist, there would be two hits to efficiency. First, the caller of indexing operations should ensure the index is not beyond the current size of the vector. Second, the new element would need to be default constructed even if you're about to assign a new value into it anyway.

    The reason for having both reserve and resize is similar. resize requires a default construction of every element. For something like vector<double> that doesn't seem like a big deal, but for vector<ComplicatedClass>, it could be a big deal indeed. Using reserve is an optimization, completely optional, that allows you to anticipate the final size of the vector and prevent reallocations while it grows.

    push_back avoids the default construction of an element, since the contents are known, it can use a move or copy constructor.

    None of this is the wrong style, use whatever's appropriate for your situation.