Move semantics







Introduction: copying temporaries
pitfall
Moving constructors
Perfect forwarding
Extending horizons: tips & tr...


Find an error and propose a fix:

vector<string>& getNames() {
vector<string> names;
names.push_back("Ivan");
names.pus...


Possible solutions:

1

void getNames(vector<string>& names) {
names.push_back("Ivan");
names.push_back("Artem");
}

ve...


Compiler:
Return Value Optimization (RVO);
Named Return Value Optimization (NRVO).

•
•


Techniques:
Copy-on-write (C...


Language:
•
•

Recognize temporary objects;
Treat temporary objects differently.
expression

glvalue

rvalue

(“generalized”
lvalue)

lvalue

xvalue
(“eXpiring”
value)

prvalue
(“pure” rvalue)
lvalue



•


•

identifies a non-temporary object.

prvalue

“pure rvalue” - identifies a temporary object or is a
valu...
class Buffer {
char* _data;
size_t _size;
// ...
// copy the content from lvalue
Buffer(Buffer const& lvalue)
: _data(null...
class Configuration {
// ...
Configuration(
Configuration const&);
Configuration const& operator=(
Configuration const& );...
Does not really move anything;
 Does cast a reference to object to
xvalue:


template<typename _T>
typename remove_refer...






Move is an optimization for copy.
Copy of rvalue objects may become
move.
Explicit move for objects without move...
Compiler does generate move
constructor/assignment operator when:



•
•
•

there is no user-defined copy or move operati...
class Configuration {
// have copy & move operations implemented
// ...
};
class ConfigurationManger {
// ...
Configuratio...
class Configuration {
// have copy & move operations implemented
// ...
};
class ConfigurationManger {
// ...
Configuratio...
 Normally

C++ does not allow reference to
reference types.
 Template types deduction often does
produce such types.
 T...
Just a cast as well;
 Applicable only for function templates;
 Preserves arguments
lvaluesness/rvaluesness/constness/etc...
class ConfigurationManger {
template <class _ConfigurationType>
ConfigurationManager(_ConfigurationType&& defaultConfig)
:...


Passing parameters to functions:

class ConfigurationStorage {
std::string _path;
// ...
template <class _String>
bool ...


Passing parameters by value:

class ConfigurationManger {
Configuration _current;
// ...
bool setup(
Configuration cons...


Return results:

vector<string> getNamesBest() {
vector<string> names;
// ...
return names; // OK, compiler choice for ...


Extending object life-time:

vector<string> getNames() {
vector<string> names;
// ...
return names;
}
// ...
vector<str...
The hardest work for move semantic
support usually performed by the compiler
and the Standard Library.
 There is still a ...
C++ 11 usage experience
Upcoming SlideShare
Loading in …5
×

C++ 11 usage experience

1,033
-1

Published on

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

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

Published in: Education, Technology, Business
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,033
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
33
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

C++ 11 usage experience

  1. 1. Move semantics
  2. 2.      Introduction: copying temporaries pitfall Moving constructors Perfect forwarding Extending horizons: tips & tricks Q&A
  3. 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. 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. 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. 6.  Language: • • Recognize temporary objects; Treat temporary objects differently.
  7. 7. expression glvalue rvalue (“generalized” lvalue) lvalue xvalue (“eXpiring” value) prvalue (“pure” rvalue)
  8. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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.
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×