A little more about C++ references

This commit is contained in:
Geoff Liu 2015-08-30 14:20:18 -06:00
parent a6af51e42f
commit 1d1def16a5

View File

@ -4,6 +4,7 @@ filename: learncpp.cpp
contributors:
- ["Steven Basart", "http://github.com/xksteven"]
- ["Matt Kline", "https://github.com/mrkline"]
- ["Geoff Liu", "http://geoffliu.me"]
lang: en
---
@ -248,6 +249,56 @@ const string& barRef = bar; // Create a const reference to bar.
// Like C, const values (and pointers and references) cannot be modified.
barRef += ". Hi!"; // Error, const references cannot be modified.
// Sidetrack: Before we talk more about references, we must introduce a concept
// called a temporary object. Suppose we have the following code:
string tempObjectFun() { ... }
string retVal = tempObjectFun();
// What happens in the second line is actually:
// - a string object is returned from `tempObjectFun`
// - a new string is constructed with the returned object as arugment to the
// constructor
// - the returned object is destroyed
// The returned object is called a temporary object. Temporary objects are
// created whenever a function returns an object, and they are destroyed at the
// end of the evaluation of the enclosing expression. So in this code:
foo(bar(tempObjectFun()))
// assuming `foo` and `bar` exist, the object returned from `tempObjectFun` is
// passed to `bar`, and it is destroyed before `foo` is called.
// Now back to references. The exception to the "at the end of the enclosing
// expression" rule is if a temporary object is bound to a const reference, in
// which case its life gets extended to the current scope:
void constReferenceTempObjectFun() {
// `constRef` gets the temporary object, and it is valid until the end of this
// function.
const string& constRef = tempObjectFun();
...
}
// Another kind of reference introduced in C++11 is specifically for temporary
// objects. You cannot have a variable of its type, but it takes precedence in
// overload resolution:
void someFun(string& s) { ... } // Regular reference
void someFun(string&& s) { ... } // Reference to temporary object
string foo;
someFun(foo); // Calls the version with regular reference
someFun(tempObjectFun()); // Calls the version with temporary reference
// For example, you will see these two versions of constructors for
// std::basic_string:
basic_string(const basic_string& other);
basic_string(basic_string&& other);
// Idea being if we are constructing a new string from a temporary object (which
// is going to be destroyed soon anyway), we can have a more efficient
// constructor that "salvages" parts of that temporary string. You will see this
// concept referred to as the move semantic.
//////////////////////////////////////////
// Classes and object-oriented programming
//////////////////////////////////////////