2.2 Move Semantics

What was the problem

Copies! Copies everywhere! And dynamic allocations too!

So was the world before C++11. In these old days, if we had to pass a large object to a function that needed its own instance of it, then we would have certainly created a copy of it.

struct catalog 
{ 
  catalog(const std::vector<item>& entries) 
    // Here we have one allocaction, for the storage, 
    // plus copies of the elements from the vector. 
    : m_entries(entries) 
  {} 
 
private: 
  std::vector<item> m_entries; 
}; 
 
void create_catalog(int n) 
{ 
  // One allocation of n items, plus their initialization. 
  std::vector<item> entries(n); 
 
  // ... 
 
  catalog c(entries); 
  // I don’t need the entries anymore, but they are still here. 
}
How the Problem is Solved

PIC <utility>

C++11 introduces the move semantics and the std::move() function. In practice it means far fewer copies, as the instances’ data is transfered from one place to another.

struct catalog 
{ 
  // Note the pass-by-value for the argument. 
  catalog(std::vector<item> entries) 
    // Explicit transfer into m_entries, no allocation. 
    : m_entries(std::move(entries)) 
  {} 
 
private: 
  std::vector<item> m_entries; 
}; 
 
void create_catalog(int n) 
{ 
  // The single allocation in this program. 
  std::vector<item> entries(n); 
 
  // ... 
 
  // I don’t need the entries anymore, so I transfer them. 
  catalog c(std::move(entries)); 
}

In the example above, there is only one allocation, for the vector of entries in create_catalog(), and zero copies. The ownership of the allocated space is actually transfered from one vector to another every time std::move() is used, until it ends up in m_entries.