4

Consider the following code:

#include <iostream>
#include <string>

struct my_struct {
    void func(std::string&& str) {
        str_ = str;
    }

    std::string str_;
};

int main() {
    my_struct s;
    std::string str("Hello");

    s.func(std::move(str));

    std::cout << str << std::endl;
    std::cout << s.str_ << std::endl;    
}

Why do I need an extra std::move in my_struct::func in order to invoke the move assignment operator of std::string? What would the extra std::move exactly do? I thought it would just cast the given type to its rvalue reference counterpart?

Florian
  • 1,036
  • 10
  • 15

2 Answers2

3

When you do str_ = str;, str is a named variable. That means inside your function str is an lvalue, not an rvalue. This means copy assignment is used and not move assignment.

What you need to do is get str back to an rvalue and you can do that with std::move like

str_ = std::move(str);
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • What I recently learned from http://stackoverflow.com/questions/9779079/why-does-c11-have-implicit-moves-for-value-parameters-but-not-for-rvalue-para is that `std::move` actually generates an xvalue which is a special rvalue. – Florian Sep 09 '16 at 04:48
3
void func(std::string&& str) {
    str_ = str;
}

should be

void func(std::string&& str) {
    str_ = std::move(str);
}

as str has a name, and so is a lvalue.

Jarod42
  • 203,559
  • 14
  • 181
  • 302