What happened when assigning an rvalue reference to lvalue?

cannot bind rvalue reference of type to lvalue of type
std::move
c++ rvalue references explained pdf
lvalue and rvalue in c++11
c return rvalue reference
c convert rvalue reference to lvalue reference
const rvalue reference
c assign rvalue to reference

I have a simple example:

void Message::move_Folders(Message *m) {
    m_folders = std::move(m->m_folders);
    for (auto f : m_folders) {
        f->removeMessage(m);
        f->addMessage(this);
    }
    m->m_folders.clear();
}

This function can move the "folders" member from one to another. So I want to know: Need I provide a move assign function for "folders"?

folders &operator=(folders &&f) {
    ...
}

What happened when assigning an rvalue reference to lvalue? Is it still a copy operation? (I believe not.)

Note: folders is a set of the Folder objects. A message may belong to many folders. So a message contains a set of Folders. The Folder also has a member messages. A folder may contain many messages. It's a little complicated.

This is the definition of Message and Folder:

class Message {
public:
// constructor and destructor
...
private:
    std::set<Folder *> m_folders;
...
};

class Folder {
friend class Message;
//constructor and destructor
...
private:
    std::set<Message *> m_messages;
};

Thanks

Note that std::move does not move a thing; rather it makes the thing movable. So in order to actually move the m->folders into this->folders, indeed the move assignment must perform that logic.

In fact, that move assignment should be the one responsible to define the move semantics: the move_folders method does not have to clear m->folders since it should not know this detail.

Understanding lvalues, rvalues and their references, Indeed, you can read about rvalue references in C++ reference books and Now an lvalue reference is a reference that binds to an lvalue. lvalue references are to from disposable instances, with the move assignment operator: In fact, by a tweak in template argument deduction, the following happens:. And an rvalue reference is a reference that binds to an rvalue. rvalue references are marked with two ampersands (&&). Note that there is one exception: there can be lvalue const reference binding to an rvalue. Anyway, let’s not worry about this case just now, let’s focus on the big picture first. What is this all for?

The need to provide a user defined move assignment depends on what other special members you have already defined, see the image for combinations:

So if Folders does not have a user defined destructor, copy constructor or assignment operator, then move constructor and assignment will be implicitly declared by the compiler. Otherwise you will need to write one yourself.

What happened when assigning an rvalue to lvalue? Is it still a copy operation? (I believe not.)

It depends if you have a move assignment it will move, else it will copy.

Finally do you need move assignment for your Folder class to move std::set is actually No, since the move assignment of std::set does not move the contents one by one with the default allocator.

Understanding lvalues and rvalues in C and C++, So what do lvalue and rvalue mean in C and C++? This is what I intend to Non-​const lvalue references cannot be assigned rvalues, since that would rvalue is being built and then assigned to v2 (this can happen for some  On the left side we have the reference (an lvalue) that should point to an existing object. But being 10 a numeric constant, i.e. without a specific memory address, i.e. an rvalue, the expression clashes with the very spirit of the reference. If you think about it, that's the forbidden conversion from rvalue to lvalue.

You do not need to provide a move-assignment operator, but if you don't the call will indeed be downgraded to a copy.

Rvalue references and std, Returning a value from a function will turn that value into an rvalue. Once you call return on This is where the performance benefits of move constructors happen. Move-assignment operators work and look the same as a Move constructor. lvalue and rvalue in C language L-value: “l-value” refers to memory location which identifies an object. l-value may appear as either left hand or right hand side of an assignment operator (=). l-value often represents as identifier. Expressions referring to modifiable locations are called “ modifiable l-values “.

15.2, Since r-values have expression scope, if we were to assign a value L-value references to const objects can be initialized with l-values and r-values alike. What you're observing is happening because `ref` is not an r-value. Example: Certain kinds of expressions involving rvalue references (8.3.2) yield xvalues, such as a call to a function whose return type is an rvalue reference or a cast to an rvalue reference type. An lvalue is a glvalue that is not an xvalue. An rvalue is a prvalue or an xvalue.

C++ rvalue references and move semantics for beginners, Such rvalue reference lets you modify the value of a temporary object: it's like removing the The key point of the copy constructor and the assignment operator is that they both receive a Does that happen all the time? (link) Lvalue An expression can appear on the left side of an assignment expression if the expression is not const qualified. Xvalue. An rvalue reference that is to expire. (Prvalue) rvalue A non-xvalue expression that appears only on the right side of an assignment expression. Rvalues include both xvalues and prvalues.

Understanding Move Semantics and Perfect Forwarding: Part 2, In the previous article I discussed lvalues and rvalues, what they mean and how An rvalue reference is a reference that is only assigned an rvalue, meaning you In the above move constructor the following things occur. rvalue references are introduced in C++11 and rvalue references can do what lvalue references fails to do i.e. a rvalue reference can refer to rvalues.

Comments
  • in your example folders is a member variable and a type, thats rather confusing
  • folders is a set of the Folder objects. A message may belong to many folders. So a message contains a set of Folders.
  • @ZhenYang please include the definition of folders in the question, I think not havng it is causing confusion. Please read minimal reproducible example
  • @RichardCritten I have added the definition of Message and Folder. I think the std::set has performed the move-assignment. Do you think so? But the m->m_folders.clear(); is unnecessary as xtofl said.
  • folders &operator=(folders &&f) should probably be Folder& operator=(Folder&& f) , thats what initially caused my confusion
  • I missed something. The 'folders' is a set of 'Folder'. It's an std::set. So the expression: 'folders = std::move(m->folders);' will call the std::set move-assignment to move. I don't need to do anything. Right?
  • That's right. Actually I missed that fact. My guess is that the set move assignment does a clear of the incoming argument. I'm not sure that's guaranteed, though. On the other hand, it should not matter.
  • Thanks for your help.
  • Note that after move std::set is in an unspecified valid state, where you can call methods on it without any preconditions, but if you are want to continue using it e.g. inserting items in it, then you need to call clear to set it to a specified state.
  • Note that even though folders currently is an std::set, the "express ideas directly in code" guideline hints that you should create a class for it (which may use a set for convenience). Cf. isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rp-direct
  • Yes, I get it. But the picture is a bit complicated. I need time to understand it.
  • Credit where credit is due. Where does the picture come from?
  • Howard Hinnant's presentation "Everything You Ever Wanted To Know About Move Semantics (and then some)" from ACCU 2014 conference
  • Yes. If the folders is not an std::set, it will be a copy.