diff options
Diffstat (limited to 'c++.html.markdown')
| -rw-r--r-- | c++.html.markdown | 82 | 
1 files changed, 77 insertions, 5 deletions
| diff --git a/c++.html.markdown b/c++.html.markdown index ff2a98fd..8a7f5a59 100644 --- a/c++.html.markdown +++ b/c++.html.markdown @@ -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  --- @@ -158,11 +159,12 @@ void foo()  int main()  { -    // Assume everything is from the namespace "Second" -    // unless otherwise specified. +    // Includes all symbols from `namesapce Second` into the current scope. Note +    // that simply `foo()` no longer works, since it is now ambiguous whether +    // we're calling the `foo` in `namespace Second` or the top level.      using namespace Second; -    foo(); // prints "This is Second::foo" +    Second::foo(); // prints "This is Second::foo"      First::Nested::foo(); // prints "This is First::Nested::foo"      ::foo(); // prints "This is global foo"  } @@ -248,6 +250,59 @@ 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 (Well, this is what the +// standard says, but compilers are allowed to change this behavior. Look up +// "return value optimization" if you're into this kind of details). 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  ////////////////////////////////////////// @@ -680,7 +735,7 @@ class Foo {    virtual void bar();  };  class FooSub : public Foo { -  virtual void bar();  // overrides Foo::bar! +  virtual void bar();  // Overrides Foo::bar!  }; @@ -699,7 +754,8 @@ pt2 = nullptr;  // Sets pt2 to null.  // '=' != '=' != '='! -// Calls Foo::Foo(const Foo&) or some variant copy constructor. +// Calls Foo::Foo(const Foo&) or some variant (see move semantics) copy +// constructor.  Foo f2;  Foo f1 = f2; @@ -713,6 +769,22 @@ Foo f1 = fooSub;  Foo f1;  f1 = f2; + +// How to truly clear a container: +class Foo { ... }; +vector<Foo> v; +for (int i = 0; i < 10; ++i) +  v.push_back(Foo()); + +// Following line sets size of v to 0, but destructors don't get called, +// and resources aren't released! +v.empty(); +v.push_back(Foo());  // New value is copied into the first Foo we inserted in the loop. + +// Truly destroys all values in v. See section about temporary object for +// explanation of why this works. +v.swap(vector<Foo>()); +  ```  Further Reading: | 
