1

I know the differences between T& operator[](); and T operator[](), the former one returns a reference, the latter one returns a copy of the result.

But what confuses me is that the same expression container[idx] could be used in the return statement for the two different kinds of return types in the declarations.

How is this goal (one returns a reference, the other returns a copy) is achieved by the compiler?

Here is the code snippet:

template<typename T>
class Array
{
 public:
 #ifdef RETURN_REFERENCE
    T& operator[](int idx)
 #else
    T  operator[](int idx)
 #endif
    {
         assert(idx<size);
         return container[idx];  // same expression works for T and T&
    }
 private:
    enum {size =100};

    T container[size];
}
cigien
  • 57,834
  • 11
  • 73
  • 112
John
  • 2,963
  • 11
  • 33
  • Like you said, one returns a reference, and one returns a copy. What is your actual question? – Remy Lebeau Dec 27 '20 at 02:38
  • @RemyLebeau Why the same code snippet could be used by two different declarations. How this goal (one returns reference, the other returns a copy) is achieved by the compiler? – John Dec 27 '20 at 02:41
  • How can the expression `container[idx]` be typed as either `T` or `T&` -- is that basically the question? – Noah Dec 27 '20 at 02:46
  • Yes, this the basic question. @Noah – John Dec 27 '20 at 03:06
  • Looking at the comment, it seems you are asking why the same expression can be returned by copy, or by reference. – cigien Dec 27 '20 at 03:23
  • @cigien Yes, why the same expression can be returned by copy, or by reference.Sorry for misleading, English is not my mother language. – John Dec 27 '20 at 03:25
  • No worries, your English is fine. Go ahead and add that information to the question please. – cigien Dec 27 '20 at 03:27
  • @cigien I edited just now almost at the same time with your last comment. :) – John Dec 27 '20 at 03:29
  • Thanks for editing. I cleaned up the text a little bit. You can get some ideas from this for how to make questions a little clearer. – cigien Dec 27 '20 at 03:35
  • Generally speaking, the expression `container[idx]` is a reference (means of indirectly accessing) an array element. If the function returns a reference, the reference obtained by evaluating `container[idx]` is returned "as is" to the caller (in the sense that calling code can't tell the difference). If the function returns by value, the reference `container[idx]` is used to access the referred-to value and somehow copy that value to the caller. Every compiler (and even the same compiler with different settings) may do those things in different ways. – Peter Dec 27 '20 at 04:26
  • @cigien I see. Thank you. I try my best to do better next time. – John Dec 27 '20 at 05:22

1 Answers1

3

It's fundamentally no different from this case:

int i = <whatever>;
int &j = i; //Reference
int k = i; //Copy

The i expression does not stand alone. It is being used in a specific context, and the nature of that context determines what happens to the expression.

The return statement is performed in the context of the type of the return value. For example, if the returned expression is different from the type of the return value, the compiler will attempt to convert the expression to the appropriate type (much like float q = i; would convert i to a float).

The expression by itself just identifies an object. What happens to the object being identified depends on how it gets used. If it's used to initialize a reference, then a reference to that object is created. If it's used to initialize another object of that type, then a copy is created.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982