Skip to content

Latest commit

 

History

History
168 lines (120 loc) · 5.83 KB

File metadata and controls

168 lines (120 loc) · 5.83 KB

Move is not a silver bullet, it has issues too

Not every type is movable (and/or copyable)

class openfile {
    FILE* f;
  public:
    explicit openfile(const char* filename) : f(std::fopen(filename, "rw")){
      if(!f){throw std::runtime_error("unable to open file");}
    }
    ~openfile(){fclose(f);}
    void write(const char* message);
    // copy suppressed
};

Where should f point if openfile has been moved from? If the class wants to support move semantic, it has to change it’s invariants.

Language complexity

It makes the language specification more complex.

Move is not always an optimisation

As a copy is a valid move implementation, moves are not necessarily cheaper than copies

Which advantages does move-semantic provide?

Performance

temporaries and expiring values are cheap

std::vector<std::string> create() {
  std::vector<std::string> coll;
  coll.reserve(3);
  // ...
  coll.push_back(s+s); // because of push_back(T&&) and std::string(std::string&&);
  coll.push_back(std::move(s)); // because of push_back(T&&) and std::string(std::string&&);
  return coll; // because of std::vector<T>(std::vector<T>&&) and std::string(std::string&&);
}
  • returning locals by value is cheap

  • temporaries (unnamed) are cheap

  • it is possible to "mark" manually a value as temporary

Which advantages does move-semantic provide

Simpliciteness: it is possible to return uncopyable (but moveable) types from function without adding further indirections.

struct type_with_costly_or_no_copy_constructor{ /* ... */};

// allocates unnecessarily (which is a costly operation) to avoid a potential copy
// should the caller check for nullptr?
// does it point to one or more elements?
// is the pointed content shared with someone else?
// is it an owning pointer?
// should the caller free it? If yes, how?
type_with_costly_or_no_copy_constructor* factory();

// no overhead, less documentation needed, no leaks by design
type_with_costly_or_no_copy_constructor factory();

Which advantages does move-semantic provide

Correctness: before C++11 it was not possible to implement something like std::unique_ptr. It’s C++03 counterpart, std::auto_ptr has been declared as broken beyond repair.

It’s copy constructor does not copy, so, for example, it’s not safe to use with stl algorithms, containers and other functions.

// suppose that all pointer are != nullptr
std::auto_ptr<int> v[N] = { /* ... */ };
std::sort(v, v + N,
  [](const std::auto_ptr<int>& lhs, const std::auto_ptr<int>& rhs){
      return *lhs < *rhs;
}); // might crash if sort makes an internal temporary copy

Which advantages does move-semantic provide

Consistency: eases generic programming. The containers and algorithm from the standard library do work correctly ™ with std::unique_ptr, but do not with std::auto_ptr. And they do not require any special or separate implementation.