C++: std::vector [] operator

2020-04-05 07:27发布

问题:

Why std::vector has 2 operators [] realization ?

reference       operator[]( size_type pos );
const_reference operator[]( size_type pos ) const;

回答1:

One for non-const vector object, and the other for const vector object.

void f(std::vector<int> & v1, std::vector<int> const & v2)
{
   //v1 is non-const vector
   //v2 is const vector

   auto & x1 = v1[0]; //invokes the non-const version
   auto & x2 = v2[0]; //invokes the const version

   v1[0] = 10; //okay : non-const version can modify the object
   v2[0] = 10; //compilation error : const version cannot modify 

   x1 = 10; //okay : x1 is inferred to be `int&`
   x2 = 10; //error: x2 is inferred to be `int const&`
}

As you can see, the non-const version lets you modify the vector element using index, while the const version does NOT let you modify the vector elements. That is the semantic difference between these two versions.

For more detail explanation, see this FAQ:

  • The Rule of Thumb: Subscript operators often come in pairs!

Hope that helps.



回答2:

To make this differentiation possible:

// const vector object, cannot be modified
// const operator[] allows for this
int get_value(const std::vector<int>& vec, size_t index)
{
   return vec[index];
}

// non-const vector object can be modified
// non-const operator[] allows for this
void set_value(std::vector<int>& vec, size_t index, int val)
{
   vec[index] = value;
}

std::vector<int> values;
values.push_back(10);
values.push_back(20);

set_value(values, 0, 50);
get_value(values, 0);


回答3:

one so that you can modify and read from a (non const) vector

void foo( std::vector<int>& vector )
{
    // reference operator[]( size_type );
    int old = vector[0];
    vector[0] = 42;
}

one so that you can read from a const vector

void foo( std::vector<int> const& vector )
{
    //const_reference operator[]( size_type ) const;
    int i = vector[0];

}


回答4:

One of the two overloads allows you to retrieve a const reference to an element of a vector accessed through a const variable. The other one allows you to obtain a non-const reference to an element of a vector accessed through a non-const variable.

If you didn't have the const version, you wouldn't be allowed to compile the following for instance:

void f(vector<int> const& v)
{
    cout << v[0]; // Invokes the const version of operator []
}

In the following example, instead, the non-const version is invoked, which returns a non-const reference to the first element in the array and allow, for instance, to assign a new value to it:

void f(vector<int>& v)
{
    v[0] = 1; // Invokes the non-const version of operator[]
}