0

I was reading Effective C++ by Scott Meyers and came across this. The reasons for using references/pointers over each other contained this:

string s1("Nancy");
string s2("Clancy");
string& rs = s1; // rs refers to s1
rs = s2; //rs still refers to s1, but s1's value is now "Clancy".

So, I tried this out:

string s1("Nancy");
string s2("Clancy");
string& rs = s1;
cout << rs << endl;
rs = s2;
cout << rs << endl;
cout << s1 << endl;

Output seen:

nancy
clancy
clancy

That means s1's value is now changed and The original value of s1 is lost forever??

This is one of the things that differentiates references from pointers then??Use references over pointers only when you are sure that you are not going to refer to different objects at different time??

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
basav
  • 1,475
  • 12
  • 20

2 Answers2

5

C++ Standard n3337

§ 5.17 Assignment and compound assignment operators

2) In simple assignment (=), the value of the expression replaces that of the object referred to by the left operand.

(...)

6) When the left operand of an assignment operator denotes a reference to T, the operation assigns to the object of type T denoted by the reference.

§ 8.5.3 References

1) A variable declared to be a T& or T&&, that is, “reference to type T” (8.3.2), shall be initialized by an object, or function, of type T or by an object that can be converted into a T.(...)

2) A reference cannot be changed to refer to another object after initialization. Note that initialization of a reference is treated very differently from assignment to it. Argument passing (5.2.2) and function value return (6.6.3) are initializations.

3) The initializer can be omitted for a reference only in a parameter declaration (8.3.5), in the declaration of a function return type, in the declaration of a class member within its class definition (9.2), and where the extern specifier is explicitly used.

You cannot reinitialize a reference in C++ 1. You can assign different value to the object it refers to. This is one and the same object for that reference forever. And this is what you did in your example.

string s1("Nancy")   // s1 Nancy
string s2("Clancy"); // s2 Clancy
string& rs = s1;     // rs-> s1
cout<<rs<<endl;      // ==cout s1
rs=s2;               // == s1=s2  
                     // s1 Clancy
                     // s2 Clancy
cout<<rs<<endl;      // ==cout s1
cout<<s1<<endl;

That means s1's value is now changed and The original value of s1 is lost forever??

Yes.

This is one of the things that differentiates references from pointers then?

Yes. A pointer can be reinitialized and the reference cannot. This is the first difference pointed out here

What are the differences between a pointer variable and a reference variable in C++?

When to use references vs. pointers

Use references over pointers only when not reinitialising it?

Use them when you want always point to the same object. Use them as well if it is a member of a class and you want to preserve an invariant that valid object of that class always contains a reference to something. Reference member must always be initialized when class instance is constructed so in that way reference enforces you to preserve invariant.


1 As @James Kanze pointed out in the comments you cannot in fact reinitialize anything in C++ in proper technical meaning of this word. In most cases initialization involves constructor and that (ctor) is called only once, at the beginning of object's lifetime (initialization of a reference is special in this context as § 8.5.3/2 points out in that reference is initialized by passing an argument or returned value from function). After this happened there is only an assignment, i.e call to T& operator=(T const&)

Community
  • 1
  • 1
4pie0
  • 29,204
  • 9
  • 82
  • 118
  • spot on with the analysis...+1 for that...But I thought references are not to be initialised again and the compiler would make sure of that. – basav Jan 25 '15 at 16:16
  • you didn't initialize it again, you assigned a new value to the object that reference was initialized with. It will always reference that same object, here s1. – 4pie0 Jan 25 '15 at 16:17
  • 1
    Just a nit, but you cannot "reinitialize" anything in C++. An object or a reference is initialized when it comes into being; after that, there is just assignment. And initialization and assignment are two different things: with references, they are radically different, but it's trivial to design a class type where they are significantly different as well. (Initialization involves a constructor; assignment the assignment operator.) – James Kanze Jan 25 '15 at 16:20
  • @James...I was wrong with the word "reinitialise"..The book states it as use a reference when "once you're referring to that object, you'll never want to refer to anything else" – basav Jan 25 '15 at 16:24
  • @JamesKanze that is absolutely true, thank you for complementing the picture – 4pie0 Jan 25 '15 at 16:26
  • now it's clearer with the explanations to my questions... – basav Jan 25 '15 at 16:34
0

To answer you question in a simple and short way.... yes the original value of "s1" is "lost" in really is changed. Why? When you create a reference variable, you are creating a variable that will have another variable as an alias. This reference variable will keep the address of the alias variable. It's like having a pointer. The R. Variable will always point to the A. Variable. However, the difference between a pointer and a R.Variable is that for pointers you dereference in a different manner, with R.Variable you treat them like normal variables, and second is that for R.Variable you don't do anything special to address its memory, as you do in Pointers.

int AliasV = 70;
int& RefeV = AliasV;

cout<<RefeV <<" "<< AliasV;

//Now RefeV is addressing to AliasV memory. (Similar to Pointer but no equal)

RefeV = 100;

//Because RefeV is addressing to AliasV memory, AliasV now has as value 100
cout<<RefeV<<" "<<AliasV;

Output:

70 70
100 100

Tip:

  • Keep in mind that a RefeVariable will always address to its alias memory behind the scenes.
  • Any changes to RefeVariable will affect its alias.
Andy
  • 349
  • 1
  • 2
  • 8