1

Why would you need a move constructor when unnamed objects only are alive until the end of the full-expressions anyway? If we had this code:

class Example6 {
    string* ptr;
  public:
    Example6 (const string& str) : ptr(new string(str)) {}
    ~Example6 () {delete ptr;}
    // move constructor
    Example6 (Example6&& x) : ptr(x.ptr) {x.ptr=nullptr;}
    // move assignment
    Example6& operator= (Example6&& x) {
      delete ptr; 
      ptr = x.ptr;
      x.ptr=nullptr;
      return *this;
    }
};


int main () {

  Example6 bar = Example6("ple");   // move-construction

  return 0;
}

We have an Rvalue reference as the parameter for the move constructor and assignment operation. In this case, bar's move constructor is called when it is initialized to a temporary of the same class. The thing that I do not understand is: Since temporaries have the lifetime of the full-expression, why is there a need for a move constructor instead of a copy constructor? I mean, implicit defined move constructor and assignment operator "erase" the data from the temporary, even though this data would all be destroyed after the semicolon, so why do you need a move constructor, which somewhat does the same as copy constructor... Why is there a need to erase data from a temporary that gets destroyed after the semicolon anyway?

  • 1
    Because the move constructor doesn't just work for temporaries, it works for anything that matches it. Sometimes you don't even have a copy constructor available to ensure move semantics only (like with `std::unique_ptr`). – JAB May 23 '17 at 20:46
  • Possible duplicate of [What are move semantics?](https://stackoverflow.com/questions/3106110/what-are-move-semantics) – Weak to Enuma Elish May 23 '17 at 20:48
  • https://stackoverflow.com/a/11077345/2066459 – Robert Jacobs May 23 '17 at 20:49
  • @JamesRoot, well I am not quite sure.. My question is mostly concerning confusion between copy and move functions, whereas that question specifically asks what move semantics are. I am not sure though. –  May 23 '17 at 21:01
  • The main purpose of moving is to avoid wasting time copying resources, and to enable better use of non-copyable opjects. Imagine if your string was 2 gigabytes long. Copying it and destroying the old would be slow at best, or cause an allocation failure / lazy-allocation crash at worst. Or if `Example6` were non-copyable then the `main` would not even compile. – M.M May 23 '17 at 21:18

3 Answers3

1

C++ added move constructors primarily to help improve performance. Proper resource management is possible without using move constructors at all. In fact, this is how C++ used to do it prior to introduction of move constructors.

The issue with copying and then destroying temporaries is that the copy constructor being called has no idea that it is given a temporary to copy. Therefore, the copy constructor must copy the data as if its source is not a temporary, potentially allocating additional resources in the process of copying the object.

When the compiler knows that you are about to copy a temporary, it lets you know that you can harvest as much internals as you wish, potentially saving you some costly allocations.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

Why is there a need to erase data from a temporary that gets destroyed after the semicolon anyway?

No, this is not why you would want a move constructor.

As you say, the values of the temporary won't matter because it's a temporary so a move constructor can "steal" the data of the temporary to avoid expensive allocations etc. That's what it's about, that's what gives you better performance with moving vs copying, not because of data that will be erased.

Moving is about gaining performance, not about making sure that data is "erased".

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
  • 1
    *Moving is about gaining performance* ... not only. It also enables us to *move* stuff around which we previously couldn't if said stuff is non-copyable (e. g. resizing an `std::vector` was not possible before move semantics) which I personally find much more exciting than the possible performance gains. – zett42 May 23 '17 at 21:12
0

Well a few reasons:

  1. Copy elision was optional but allowed pre-C++17
  2. You can move a lot more than temporaries.
  3. Rvalue references add a lot of new possibilities to the language so it can work in a more intuitive manner, and more efficiently. An example of this is unique_ptr. Without rvalue references you either end up with scoped_ptr or auto_ptr. The first is very limited in its uses, the second is broken by design because it breaks the principle of least surprise.

Note that move construction does not remove the need for copy elision. A move of primitive types is as expensive as a copy!

rubenvb
  • 74,642
  • 33
  • 187
  • 332