C++ 11 usage experience
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

C++ 11 usage experience

on

  • 907 views

В своей презентации “С++ 11 usage experience: Move semantic”, Дмитрий Гурин, bp GlobalLogic, рассказывает о части нововведений ...

В своей презентации “С++ 11 usage experience: Move semantic”, Дмитрий Гурин, bp GlobalLogic, рассказывает о части нововведений нового стандарта C++, особенностях работы с объектами rvalue и lvalue, а также особенностями использования функций std::move и std::forward. В конце доклада — полезные советы по оптимизации кода с применением возможностей нового стандарта С++.

Напомним, Embedded Kyiv TechTalk состоялся 14 декабря 2013 года.

Statistics

Views

Total Views
907
Views on SlideShare
523
Embed Views
384

Actions

Likes
2
Downloads
16
Comments
0

1 Embed 384

http://www.globallogic.com.ua 384

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

C++ 11 usage experience Presentation Transcript

  • 1. Move semantics
  • 2.      Introduction: copying temporaries pitfall Moving constructors Perfect forwarding Extending horizons: tips & tricks Q&A
  • 3.  Find an error and propose a fix: vector<string>& getNames() { vector<string> names; names.push_back("Ivan"); names.push_back("Artem"); return names; }
  • 4.  Possible solutions: 1 void getNames(vector<string>& names) { names.push_back("Ivan"); names.push_back("Artem"); } vector<string> names; getNames(names); auto_ptr<vector<string> > names( getNames()); 2 auto_ptr<vector<string> > getNames() { auto_ptr<vector<string> > names( new vector<string>); names->push_back("Ivan"); names->push_back("Artem"); return names; } vector<string> const& names = getNames(); 3 vector<string> getNames() { vector<string> names; names.push_back("Ivan"); names.push_back("Artem"); return names; }
  • 5.  Compiler: Return Value Optimization (RVO); Named Return Value Optimization (NRVO). • •  Techniques: Copy-on-write (COW); “Move Constructors”: • •  Simulate temporary objects and treat them differently.
  • 6.  Language: • • Recognize temporary objects; Treat temporary objects differently.
  • 7. expression glvalue rvalue (“generalized” lvalue) lvalue xvalue (“eXpiring” value) prvalue (“pure” rvalue)
  • 8. lvalue  •  • identifies a non-temporary object. prvalue “pure rvalue” - identifies a temporary object or is a value not associated with any object. xvalue  • either temporary object or non-temporary object at the end of its scope. glvalue  •  • either lvalue or xvalue. rvalue either prvalue or xvalue.
  • 9. class Buffer { char* _data; size_t _size; // ... // copy the content from lvalue Buffer(Buffer const& lvalue) : _data(nullptr), _size(0) { // perform deep copy ... } // take the internals from rvalue Buffer(Buffer&& rvalue) : _data(nullptr), _size(0) { swap(_size, rvalue._size); swap(_data, rvalue._data); // it is vital to keep rvalue // in a consistent state } // ... Buffer getData() { /*...*/ } // ... Buffer someData; // ... initialize someData Buffer someDataCopy(someData); // make a copy Buffer anotherData(getData()); // move temporary
  • 10. class Configuration { // ... Configuration( Configuration const&); Configuration const& operator=( Configuration const& ); Configuration(Configuration&& ); Configuration const& operator=( Configuration&& ); // ... }; class ConfigurationStorage; class ConfigurationManger { // ... Configuration _current; // ... bool reload(ConfigurationStorage& ); // ... }; bool ConfigurationManager::reload( ConfigurationStorage& source ) { Configuration candidate = source.retrieve(); // OK, call move ctor if (!isValid(candidate)) { return false; } _current = candidate; // BAD, copy lvalue to lvalue _current = move(candidate); // OK, use move assignment return true; }
  • 11. Does not really move anything;  Does cast a reference to object to xvalue:  template<typename _T> typename remove_reference<_T>::type&& move(_T&& t) { return static_cast<typename remove_reference<_T>::type&&>(t); }  Does not produce code for run-time.
  • 12.     Move is an optimization for copy. Copy of rvalue objects may become move. Explicit move for objects without move support becomes copy. Explicit move objects of built-in types always becomes copy.
  • 13. Compiler does generate move constructor/assignment operator when:  • • • there is no user-defined copy or move operations (including default); there is no user-defined destructor (including default); all non-static members and base classes are movable.  Implicit move constructor/assignment operator does perform member-wise moving.  Force-generated move operators does perform member-wise moving: • dangerous when dealing with raw resources (memory, handles, etc.).
  • 14. class Configuration { // have copy & move operations implemented // ... }; class ConfigurationManger { // ... Configuration _current; // ... ConfigurationManager(Configuration const& defaultConfig) : _current(defaultConfig) // call copy ctor { } ConfigurationManager(Configuration&& defaultConfig) // : _current(defaultConfig) // BAD, call copy ctor : _current(move(defaultConfig)) // OK, call move ctor { } // ... };
  • 15. class Configuration { // have copy & move operations implemented // ... }; class ConfigurationManger { // ... Configuration _current; // ... template <class _ConfigurationRef> explicit ConfigurationManager(_ConfigurationRef&& defaultConfig) : _current(forward<_ConfigurationRef>(defaultConfig)) // OK, deal with either rvalue or lvalue { } // ... };
  • 16.  Normally C++ does not allow reference to reference types.  Template types deduction often does produce such types.  There are rules for deduct a final type then: • • • • T& &  T& T& &&  T& T&& &  T& T&& &&  T&&
  • 17. Just a cast as well;  Applicable only for function templates;  Preserves arguments lvaluesness/rvaluesness/constness/etc.  template<typename _T> _T&& forward(typename remove_reference<_T>::type& t) { return static_cast<_T&&>(t); } template<typename _T> _T&& forward(typename remove_reference<_T>::type&& t) { return static_cast<_T&&>(t); }
  • 18. class ConfigurationManger { template <class _ConfigurationType> ConfigurationManager(_ConfigurationType&& defaultConfig) : _current(forward<_ConfigurationType>(defaultConfig)) {} // ... }; // ... Configuration defaultConfig; ConfigurationManager configMan(defaultConfig); // _ConfigurationType => Configuration& // decltype(defaultConfig) => Configuration& && => Configuration& // forward => Configuration& && forward<Configuration&>(Configuration& ) // => Configuration& forward<Configuration&>(Configuration& ) ConfigurationManager configMan(move(defaultConfig)); // _ConfigurationType => Configuration // decltype(defaultConfig) => Configuration&& // forward => Configuration&& forward<Configuration>(Configuration&& )
  • 19.  Passing parameters to functions: class ConfigurationStorage { std::string _path; // ... template <class _String> bool open(_String&& path) { _path = forward<_String>(path); // ... } }; // ... string path("somewhere_near_by"); ConfigurationStorage storage; storage.open(path); // OK, pass as string const& storage.open(move(path)); // OK, pass as string&& storage.open("far_far_away"); // OK, pass as char const*
  • 20.  Passing parameters by value: class ConfigurationManger { Configuration _current; // ... bool setup( Configuration const& newConfig) { _current = newConfig; // make a copy } bool setup( Configuration&& newConfig) { _current = move(newConfig); // simply take it } }; Configuration config; configManager.setup(config); // pass by const& configManager.setup(move(config)); // pass by && class ConfigurationManger { Configuration _current; // ... bool setup( Configuration newConfig) { // ... _current = move(newConfig); // could just take it } }; Configuration config; configManager.setup(config); // make copy ahead configManager.setup(move(config)); // use move ctor
  • 21.  Return results: vector<string> getNamesBest() { vector<string> names; // ... return names; // OK, compiler choice for either of move ctor or RVO } vector<string> getNamesGood() { vector<string> names; // ... return move(names); // OK, explicit call move ctor } vector<string>&& getNamesBad() { vector<string> names; // ... return move(names); // BAD, return a reference to a local object }
  • 22.  Extending object life-time: vector<string> getNames() { vector<string> names; // ... return names; } // ... vector<string> const& names = getNames(); // vector<string>&& names = getNames(); // vector<string> names = getNames(); // vector<string>& names = getNames(); // vector<string>&& names = move(getNames());// OK, both C++03/C++11 OK, C++11: extends life-time OK, C++11: move construction BAD, dangling reference here BAD, dangling reference here
  • 23. The hardest work for move semantic support usually performed by the compiler and the Standard Library.  There is still a lot of space for apply move semantic explicitly for performance critical parts of the application:  • It is up to developer to ensure the code correctness when the move semantic used explicitly. • The best way to add move semantic support to own class is using pImpl idiom.