1

This does not compile. Why?

#include <iostream>
#include <vector>

struct test_s {
    int a;

    test_s& operator=(test_s &&ts) {
        a = ts.a;
        ts.a = 0;
        return *this;
    }
};

int main ()
{
  std::vector<test_s> v;

  test_s ss = std::move(v.front());

  return 0;
}

Error(s):

source_file.cpp:20:10: error: call to implicitly-deleted copy constructor of 'test_s'
  test_s ss = std::move(v.front());
         ^    ~~~~~~~~~~~~~~~~~~~~
source_file.cpp:9:13: note: copy constructor is implicitly deleted because 'test_s' has a user-declared move assignment operator
    test_s& operator=(test_s &&ts) {
            ^
1 error generated

Is it possible to move an object from vector(without the call to copy assignment operator)?

  • 10
    You are invoking *move constructor*, not *move assignment operator*. – Yksisarvinen Nov 11 '19 at 13:21
  • 1
    what do you actually want to achieve? Do you want to remove the first element from the vector? – 463035818_is_not_an_ai Nov 11 '19 at 13:22
  • 5
    btw your code has UB, because there is no `v.front()` that you could move, the vector has zero elements – 463035818_is_not_an_ai Nov 11 '19 at 13:23
  • You need to also provide a **move constructor** for the `test_s` type – Davide Spataro Nov 11 '19 at 13:23
  • Similar question for copy contructor and copy assignment operator: [What's the difference between assignment operator and copy constructor?](https://stackoverflow.com/questions/11706040/whats-the-difference-between-assignment-operator-and-copy-constructor) – Yksisarvinen Nov 11 '19 at 13:25
  • 1
    lools like a [xy problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Also note that usually moving is done to be more efficient than a copy, but in your example a simple copy would be cheaper – 463035818_is_not_an_ai Nov 11 '19 at 13:26
  • You basically cannot use a vector with a value type that has neither copy constructor nor move constructor. Which is your case. – Daniel Langr Nov 11 '19 at 13:27
  • OK. Thank you all. But looks like I oversimplefied my code example. Will try to investignate what is going on further... – Alexandr Fadeev Nov 11 '19 at 13:28
  • Well... In my "real" code it was the opposite. I wrote move constructor but forgot about move assignment operator. That was the problem. – Alexandr Fadeev Nov 11 '19 at 13:40
  • 2
    @formerlyknownas_463035818 it is very difficult to ask on SO. If OP puts a lot of code he will be asked to create minimal example. If OP provides minimal you complain there is no reason to move. OP does not have to create an example where move is necessary. – Slava Nov 11 '19 at 13:46
  • @AlexandrFadeev no you did not oversimplify, you just need to know that despite `=` you have object creation here, not assignment. It should compile if you do this `test_s ss; ss = std::move( v.front() );` – Slava Nov 11 '19 at 13:49
  • @formerlyknownas_463035818 _in your example a simple copy would be cheaper_ . Thanks, but it is not only about efficiency, I use move to transfer control of a "resource" so that it will be "released" properly. – Alexandr Fadeev Nov 11 '19 at 13:56
  • @AlexandrFadeev strictly speaking also that isnt the case for your example. The control of the `int` member is not transfered to the moved-to object, you just pretend so by copying it and setting it to `0` and nothing has to be released here – 463035818_is_not_an_ai Nov 11 '19 at 13:59

1 Answers1

5

This does not compile. Why?

Because your struct test_s needs a move constructor (or a copy constructor).

The statement:

test_s ss = std::move(v.front());

constructs the object ss. Although you see the = sign, this is not an assignment.

However, you have defined a move assignment in your struct.

In accordance with this table, when the user defines the move assignment, the move constructor is not provided by the compiler. Moreover, the move operation should "fallback" on the copy but (as you see in the table), the copy constructor is implicitly deleted (as your compiler suggests as well).

Is it possible to move an object from vector(without the call to copy assignment operator)?

Well, yes.

You should define your own move constructor for your class. Actually, you should follow the rule of five.

Note: Be also aware that your code has an undefined behavior as you are trying to access to a not existing element in the vector (as pointed out by some comments).

BiagioF
  • 9,368
  • 2
  • 26
  • 50