tags:

views:

60

answers:

5

Why do we need two? Under which circumstance each of the following operator[]s are called?

  class X {
      public:
        //...
        int &operator [](int index);
        const int &operator [](int index) const;
    };
+1  A: 

If the class X instance is const the const version is called, otherwise the non-const:

void function1( X& x )
{
    x[0]; // x is non-const, non-const version is called
    x[0] = ... // allright
}

void function2( const X& x )
{
    x[0]; // x is const, const version is called
    x[0] = ... // illegal - won't compile
}

this is done to facilitate const-correctness.

sharptooth
A: 

The const one would be used if operator[] were invoked on a const X object; otherwise the non-const one.

X x;
x[42] = 42; // ok

X x_const;
x_const[42] = 42; // error: cannot assign to const reference
John Zwinck
A: 

The first one is called when the instance of the class is referred to as a non-const type. The second is called when the type that refers to the instance is const.

For example:

void check_array(X const& x)
{
   // x[0] = 2;  // That would be a compile error.  
                 // And it's GOOD that we have such a check!
   return x[1] == 5; //calls non-const version
}

void mutate_array(X& x)
{
   x[0] = 2; // calls non-const version
   if (x[1] == 5){  //calls non-const version anyway!
       X const& const_ref = x;
       return const_ref[1] == 5;  //NOW it calls const version.
   }
}

The reasons to use it are:

  • to force a check that we don't try to modify something, that shouldn't be modified (as in check_array() function)
  • to allow compiler to optimize code, knowing that certain values won't change in a block.
Pavel Shved
A: 

Using 2 versions offers additional ways for the compiler to optimize. No value can't be assigned to const int &. The second operator is called whenever the statements allow it and since the operator is const, the compiler has additional possiblities for optimization. Whenever a result is assigned to the return value of that operator, the compiler selects the first version (which is not const).

For a more complete explanation - see Scott Meyers (More) Effective C++

Tobias Langner
-1 Sounds fishy. Constant overload is called if the object is constant, else the mutable overload is called. One can also be quite sure that this is nothing to do with compiler optimizations and everything to do with const correctness in general: if you have an object that you have rights to modify, you should be able to do so; if you don't have the rights to modify, you should still have the right to do a look-up-
UncleBens
+4  A: 
foo( X x )
{
  x[0];  // non-const indexer is called
}

bar ( const X x )
{
  x[0]; //const indexer is called
}
Phillip Ngan