Your SlideShare is downloading. ×
C++11 talk
Upcoming SlideShare
Loading in...5

Thanks for flagging this SlideShare!

Oops! An error has occurred.


Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

C++11 talk


Published on

A high level presentation about the new features in C++11

A high level presentation about the new features in C++11

Published in: Technology

  • Be the first to comment

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

No notes for slide


  • 1. Talk Overview● C++11 features ● Smart pointer family ● Rvalue references ● Thread Api
  • 2. I. C++11 Smart Pointers● auto_ptr deprecated● New types ● unique_ptr ● shared_ptr / weak_ptr● Automatic garbage collection● Use RAII idiom● Exception safe● STL container safe● Work with dynamically created arrays● Pointer semantics
  • 3. unique_ptr details● auto_ptr replacement● No copy semantics allowed● Strict single ownership usage● Uses move semantics to transfer ownership● Restricted usage in STL containers● Custom deleter support
  • 4. unique_ptr example 1void doSomethingWithFoo(std::unique_ptr<Foo> fooPtr) { fooPtr->doSomething();} // fooPtr automatically destructed at the end of the main(int argc, char* argv[]) { // Foo* foo(new Foo()); // std::unique_ptr<Foo> fooPtr1(foo); // Dont do this. // std::unique_ptr<Foo> fooPtr2(foo); // A foo pointer must be owned by single unique_ptr. std::unique_ptr<Foo> fooPtr(new Foo()); // Use RAII always. … doSomethingRisky(); // Exception safe, foo cleanup on stack unwind. ... // doSomeThingWithFoo(fooPtr); // Compiler error, cannot use copy constructor. doSomethingWithFoo(std::move(fooPtr)); // Transfer ownership using explicit move. // Shouldnt access the fooPtr members after the move. ...}
  • 5. unique_ptr example 2typedef std::unique_ptr<Foo> FooUniquePtr;void doSomethingWithReference( FooUniquePtr& fooPtr) { fooPtr->doSomething();}int main(int argc, char* argv[]) { FooUniquePtr fooPtr1(new Foo(1)); FooUniquePtr fooPtr2(new Foo(2)); doSomethingWithReference(fooPtr1); // Passing a reference not ownership. std::vector<Foo*> foos; foos.push_back(fooPtr1.get()); // still own, passing just a pointer not ownership. foos.push_back(fooPtr2.get()); // ditto fooPtr1.reset(new Foo(3)); // Foo(1) gets destructed. fooPtr1 = std::move(fooPtr2); // move foo(2) into fooPtr1, causes Foo(3) destr. std::vector< FooUniquePtr> fooPtrs; fooPtrs.push_back(std::move(fooPtr1)); // Transfer ownership to the container.}
  • 6. shared_ptr details● Multi/shared ownership usage● Thread safe (similar to primitives)● Custom destructor support● Susceptible to cyclic references memory leak● Uses copy semantics● Uses an atomic reference counter internally
  • 7. shared_ptr exampletypedef std::shared_ptr<Foo> FooSharedPtr;void doSomething(FooSharedPtr fooPtr) { fooPtr->doSomething();}int main() { // Foo* foo(new Foo(1)); // Dont do this. // FooSharedPtr fooPtr1(foo); // The foo pointer is exclusively shared-owned by // FooSharedPtr fooPtr2(foo); // the two shared pointers that dont know each other. FooSharedPtr fooPtr1(new Foo(1)); FooSharedPtr fooPtr2(fooPtr1); // foo1 pointer is shared owned by the two sharedPtrs. FooSharedPtr fooPtr3; fooPtr3 = fooPtr2; // foo1 pointer is shared owned by the 3 sharedPtrs. fooPtr2.reset(new Foo(2)); // foo1 is shared by fooPtr1, fooPtr3 only. doSomething(fooPtr3); // foo1 is Shared by fooPtr1, fooPtr2 and the param.} // Both foo1, foo2 are both destroyed at the program exit.
  • 8. shared_ptr variants● Custom deleter variant ● Exception-safe way of managing OS resources, custom memory blocks etc ● e.g. int main() { FILE* fp = fopen("/tmp/temp.txt", "rw"); std::shared_ptr<File, std::function<void (File*)> filePtr(fp, [ ] (File* fp) { fclose(fp);}); fseek(filePtr.get(), 42, SEEK_SET); // Do something else with the file }● make_shared variant ● Single memory allocation ● Requires a default constructor for T ● No facility for custom deleter specification ● Sample syntax: std::shared_ptr<Foo> = std::make_shared<Foo>();
  • 9. shared_ptr gotchaBeware of shared_ptr cyclic referencese.g. typedef std::shared_ptr<Chicken> ChickenPtr; typedef std::shared_ptr<Egg> EggPtr; struct Chicken { EggPtr source_;}; struct Egg { ChickenPtr source_;}; void memoryLeakDemo1() { { ChickenPtr chickenPtr(new Chicken()); EggPtr eggPtr(new Egg()); chickenPtr->source_ = eggPtr; eggPtr->source_ = chickenPtr; // The cycle completes } // Memory leak here: Both go the Chicken and egg go out of scope here // and they are not garbage collected as each have reference to the other. }
  • 10. weak_ptr● Observes the shared_ptr without affecting its lifetime● Has to do null check on shared_ptr before using it typedef std::shared_ptr<Chicken> ChickenPtr; typedef std::shared_ptr<Egg> EggPtr; struct Chicken { std::weak_ptr<Egg> source_;}; struct Egg { std::weak_ptr<Chicken> source_;}; void memoryLeakDemo2() { { ChickenPtr chickenPtr(new Chicken()); EggPtr eggPtr(new Egg()); chickenPtr->source_ = eggPtr; eggPtr->source_ = chickenPtr; // No shared_ptr cycle here. } // The Chicken and egg are garbage collected here. }
  • 11. When to use which● Use unique_ptr when ● by default ● the single ownership usage is clear ● implementing a pImpl idiom● Use shared_ptr when ● the object needs to be shared ● not sure of the ownership details ● need flexibility in using STL containers ● using a pre-C++11 compiler● Prefer make_shared variant whenever possible
  • 12. II. Rvalue references● Core language runtime feature in C++11● Tackles two problems ● Move semantics ● Perfect forwarding● Syntactic symbol &&
  • 13. What is an Rvalue(Simple Definition)● An rvalue can only occur on the right side of an assignment(C world)● Some examples int a = 42; int b = 43; // a and b are both l-values: a = b; // ok b = a; // ok a = a * b; // ok // a * b is an rvalue: int c = a * b; // ok, rvalue on right hand side of assignment a * b = 42; // error, rvalue on left hand side of assignment
  • 14. What is an Rvalue(C++ Definition)● Rvalue: an expression that is not an lvalue● Lvalue: any expression that refers to a memory location● Some examples int i = 42; i = 43; // ok, i is an lvalue int* p = &i; // ok, i is an lvalue int& foo(); // return value has a memory location. Foo() = 42; // ok, foo() is an lvalue int* p1 = &foo(); // ok, foo() is an lvalue // rvalues: int foobar(); // return value is a temporary. int j = 0; j = foobar(); // ok, foobar() is an rvalue int* p2 = &foobar(); // error, cannot take the address of an rvalue j = 42; // ok, 42 is an rvalue
  • 15. Motivation 1● Eliminate deep copies on temporaries● Optimize certain pass-by-value cases● Some container operation optimizations● Give more flexibility to the programmer● Solve all the above problems using move semantics
  • 16. Move Semantics Example 1● C++98 template swap method template <typename T> void swap(T& a, T& b) { T temp(a); // Two copies of a. what if a is very expensive to build? a = b; // Two copies of b. b = temp; // Two copies of a again. }● C++11 template swap method uses std::move● Std::move – Converts an lvalue to rvalue template <typename T> void swap(T& a, T& b) { T temp(std::move(a)); // One copy of a if T has a move constructor. a = std::move(b); // One copy of b if T has a move assignment operator. b = std::move(temp); // One of copy of b. }
  • 17. Example 1 cont...class SomeT {public:... // Move constructor. SomeT(SomeT&& other) : obj_(other.obj_) // Copy the pointer. { other.obj_ = null; other.obj_ = nullptr; // Make sure the others obj_ is set to NULL } // Move assignment operator. SomeT& operator=(SomeT&& other) { // steal the member fields. std::swap(obj_, other.obj_); }...private: SomeLargeObject* obj_; // Some large object that is expensive to copy.}
  • 18. Example 1 more code...// A funtion that returns SomeT by value.SomeT methodThatReturnsByValue();int main(){ SomeT some_t; ... // Compiler will automatically invoke the move assignment operator // instead of the copy assignment since it is an rvalue. some_t = methodThatReturnsByValue(); std::vector<some_t> some_ts; some_ts.reserve(4); // Lets assume the vector has a capacity of 4. for (int k = 0; k < 100; ++k) // Should cause some internal vector re-sizing calls. some_ts.push_back(some_t()); // Efficient since the SomeT has move constructor.}
  • 19. Rvalue Gotchas● An rvalue parameter inside a method/function is an lvalue● Dont re-use an object that is moved class Foo { ... Foo(Foo&& other) // 1. must explicitly call std::move on bar otherwise invokes bar copy constructor. : bar(std::move( { // 2. Shouldnt access here as it is moved. } ... private: Bar bar; // Implements the move constructor and assignment operator }
  • 20. Perfect forwarding● Used to preserve the original argument type across function calls● Uses std::forward<T> to preserve the calling type● Works only on template functions and auto situations● e.g. // Binds both rvalue and lvalue references template<typename T> void f(T&& param); // auto declarations: auto&& var = ... ;
  • 21. Need for perfect forwarding● Template factory methods that need to forwardarguments● e.g.Problem: template<typename T, typename Arg> std::shared_ptr<T> factory(Arg arg) { // Passed by value even if the arg is a ref and T has a constructor that takes reference return std::shared_ptr<T>(new T(arg)); }Solution: // Matches both rvalue and lvalue references. template<typename T> std::shared_ptr<T> factory(Arg&& arg) { // preserves the arg type to the T constructor. return std::shared_ptr<T>(new T(std::forward<Arg>(arg))); }
  • 22. Rvalue refs: Do you need to care● Use smart pointers to avoid object copies● Compiler optimization of temporary copies● STL Container emplace methods● Compiler upgrade: More efficient code out-of- box
  • 23. III. C++11 Thread Api● Thread-aware memory model● Mostly compatible with boost thread api● Support for atomics, mutexes and locks● std::async, futures, packaged_tasks and promises● Conditional variables● Thread-local storage● Thread-safe Initialization (objects w/static storage, std::call_once)
  • 24. Thread class● RAII idiom to create an TOE● Works with any callable type● Beware of the destructor (must call either of join() or detach() prior)● Movable but not copyable● Example syntax: void printInt(int x) { std::count << “x = “ << x << std::endl; } int main() { … int x = 10; std::thread t(printInt, x); … // Beware of any exceptions here. t.join(); }
  • 25. Async method● Higher level template method abstraction● Returns the result via a future object● Two different implementations with similar API int funcToRun(); int main() { std::future<int> f = std::async(funcToRun); … int result = f.get(); // get the result now. } // funcToRun is executed per a launch policy: // Default: Implementation chooses one // std::launch::async: Run asynchronously. // std::launch::deferred: Run synchronously if f.get() called.
  • 26. packaged_task class● High level template class abstraction● Encapsulates a callable type● Has a method that returns a future● Can be launched on the same thread or a different one● Makes thread-pool implementations easier
  • 27. packaged_task example#include <iostream>#include <future>#include <thread>int main(){ std::packaged_task<int()> task([](){return 7;}); // pass lambda std::future<int> result = task.get_future(); // get a future std::thread(std::move(task)).detach(); // launch on a thread std::cout << "Waiting..."; result.wait(); std::cout << "Done!nResult is " << result.get() << n;}
  • 28. Thread-safe initialization● Singleton pattern support using call_once void init_resource(Resource* rptr) { rptr = new Resource(); } std::once_flag resource_flag; Resource* r_ptr; void foo() { std::call_once(resource_flag, init_resource, r_ptr); // thread-safe once initialization r_ptr->do_something(); }● Thread-safe local static variable initialization class MyClass; MyClass& getInstance() { static MyClass instance; // Thread-safe in C++11 return instance; }
  • 29. Thread Api Gotcha● Arguments passed to std::thread, std::async, and std::call_onceare unconditionally copied to thread private area std::thread t(f, arg1, arg2, arg3, ...); // copy of f is called with copies of args. auto fut = std::async(f, arg1, arg2, arg3, ...); // same as above std::call_once(flag, f, arg1, arg2, arg3, ...); // ditto● What does this mean? void processData(const SensorData& d); // fn that takes Pass-by-reference int main() { SensorData *pd = new (SensorAddr) SensorData; std::thread t(processData, *pd); // doesnt work as expected … t.join(); }
  • 30. How You Work Around It● Use Lambdas with by-reference captures // closure copied, but it holds refs to args std::thread t([&]{ return f(arg1, arg2, arg3, ...); });● Arguments wrapped via std::ref and std::cref // Use ref wrappers to explicitly tell the intent auto fut = std::async( f, std::ref(arg1), arg2, std::cref(arg3), ...);