diff options
author | Ian Bertolacci <ian.bertolacci@gmail.com> | 2015-10-02 10:15:08 -0600 |
---|---|---|
committer | Ian Bertolacci <ian.bertolacci@gmail.com> | 2015-10-02 10:15:08 -0600 |
commit | 53790a00980f0ab58efeea5a20c97366daeca401 (patch) | |
tree | 60cced8d7b62becacd31b6fb56d9a7c41f1de809 /c++.html.markdown | |
parent | 938720074b8b18a9ada93fb8a040b9ca1a813747 (diff) | |
parent | d5b5b19ca909b573d0b0623604f1ff9369ab04ff (diff) |
Merge branch 'master' of github.com:adambard/learnxinyminutes-docs
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: |