Return to tutorial index

References and Constants

Table of Contents

  1. What is a reference?
  2. A class object (i.e. not a built-in object) may be returned by reference or passed by reference for better efficiency.
  3. When used properly, returning by reference allows the function to appear on the left-hand side of an expression.
  4. Passing/returning by reference allows the referenced object to be modified.
  5. If the intention of the class designer is to avoid modification of the passed/returned object, the reference should be made const.
  6. If a member function will not modify its data members, make the member function const.
  7. It is illegal to modify any object or reference that is declared const. Therefore, constant objects and references may only call constant member functions.

What is a reference?

A reference is nothing more than an alias. Anything you do with a reference you are actually doing to the object you are referencing.
float x=3.14;
float& intref=x;     // intref is a reference to x
float* ptr=&intref;  // ptr holds the address of x

float y=2.58;
intref=y;            // x is now equal to 2.58

Another simple example:
void func(float& fr)
{
  fr=99.99;
}

int main()
{
  float x=3.14;
  cout << x << endl;  // prints 3.14
  func(x);
  cout << x << endl;  // prints 99.99
  return 0;
}

A class object (i.e. not a built-in object) may be returned by reference or passed by reference for better efficiency.

Given:
class Book {  
//...
};

class Backpack {
public:
  Book& getContents();
  void setContents(Book& bk);
private:
  Book myText;
};
Book& Backpack::getContents()
{
  return myText;
}
void Backpack::setContents(Book& bk)
{
  myText=bk;
}
The member functions getContents() and setContents() use references to avoid inefficient temporaries:
int main()
{
  Book fiction;
  Book somebook;
  Backpack myPack;
  myPack.setContents(fiction); // in setContents source, bk is a reference
                               // to fiction, not an inefficient temporary
  somebook=myPack.getContents();  // myText is returned by reference
  return 0;
}

When used properly, returning by reference allows the function to appear on the left-hand side of an expression.

float& max(float& lhs, float& rhs)
{
  if(lhs>rhs)
    return lhs;
  else
    return rhs;
}

int main()
{
  float x=2.58;
  float y=3.14;

  max(x,y)=99.99;
  cout << x << endl;  // prints 2.58
  cout << y << endl;  // prints 99.99
  return 0;
}

Passing/returning by reference allows the referenced object to be modified.

class Backpack {
public:
  Book& getContents();
  void setContents(Book& bk);
private:
  Book myText;
};
Book& Backpack::getContents()
{
  return myText;
}
void Backpack::setContents(Book& bk)
{
  myText=bk;
  Book x;
  bk=x;   //change the object bk refers to
}
int main()
{
  Book fiction;
  Book nonfiction;
  Backpack myPack;
  myPack.setContents(fiction); // fiction will be the same as "x" in the
                               // function definition
  myPack.getContents()=nonfiction;  // myText is assigned the contents of
                                    // nonfiction
  return 0;
}

If the intention of the class designer is to avoid modification of the passed/returned object, the reference should be made const.

class Backpack {
public:
  const Book& getContents();
  void setContents(const Book& bk);
private:
  Book myText;
};
const Book& Backpack::getContents()
{
  return myText;
}
void Backpack::setContents(const Book& bk)
{
  myText=bk;
  Book x;
  bk=x;   //This line is now illegal and won't compile.
}
int main()
{
  Book nonfiction;
  Backpack myPack;
  myPack.getContents()=nonfiction;  // This line is now illegal and
                                    // won't compile
  return 0;
}

If a member function will not modify its data members, make the member function const.

class Backpack {
public:
  const Book& getContents() const;
  void setContents(const Book& bk);
private:
  Book myText;
};
Note that the setContents() member function is not made const because it modifies the object's data members (it changes myText).

It is illegal to modify any object or reference that is declared const. Therefore, constant objects and references may only call constant member functions.

class Backpack {
public:
  const Book& getContents() const;
  void setContents(const Book& bk);
private:
  Book myText;
};

int main()
{
  Backpack bp;
  const Backpack cbp;
  cbp.setContents(bp); // This line is illegal because cbp may only call
                       // constant member functions (like getContents)
  return 0;
}
Even if the member function does not actually modify the const object, the const object cannot call the function if it isn't declared as a constant member function.
Return to tutorial index

Revision History

2009 July 15 Corrected typo code: "retrn" to "return"