• Create Account

# Am I thinking about r-values correctly?

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

3 replies to this topic

### #1Servant of the Lord  Crossbones+   -  Reputation: 12521

Like
1Likes
Like

Posted 22 March 2013 - 12:45 PM

Trying to refresh and lock-in my understanding. If I do this:
std::string DoSomething(std::string &&text)
{
std::string newText = text;

//...alter 'newText'

return newText;
}

std::string strA;
strB = DoSomething(strA); //Copies 'strA'. 'strA' is not altered.
strC = DoSomething(std::move(strA)); //Moves 'strA' into 'strC', avoiding a copy, but 'strA' is now undefined.
strD = DoSomething("string literal"); //Uses move semantics, avoiding a copy.
Am I correct in thinking an lvalue passed into this function taking an rvalue, would not modify the original variable?

Do I even need to do "std::string newText = text;"? Do rvalue references, passed an lvalue, become lvalue references, or lvalues?
Basically, does rvalue references decay into pass-by-reference, or pass-by-value, when given a non-const lvalue or lvalue reference.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputation: 8488

Like
3Likes
Like

Posted 22 March 2013 - 01:01 PM

Passing an lvalue to a function that only takes an rvalue reference shouldn't even compile. However, your function as written doesn't modify the referred to string. When you refer to an rvalue reference by name it's treated as a lvalue reference (I know, uninituitive). You need to use std::move() inside the function body on the rvalue reference (or otherwise cast it to an rvalue reference) for it be treated as an rvalue reference.

### #3King Mir  Members   -  Reputation: 1302

Like
3Likes
Like

Posted 22 March 2013 - 02:55 PM

SiCrane is right to point out that you need to use std::move inside DoSomething.

The only time an lvalue reference binds an rvalue reference, is in when it's a deduced type, such as a template dependant type, an auto type, or an argument to decltype. Using declarations may also qualify. In these case the rvalue reference behaves as a universal reference, used for perfect forwarding. Whenever an lvalue is passed to such a type, the deduced type is an lvalue reference. In all other cases, the code will not compile.

Also note, the only reason strA cannot be used after it's moved, is because the library part of the standard says so. std::move does not by itself cause that. You could write a class which is safe to move then use.

Edited by King Mir, 22 March 2013 - 03:01 PM.

### #4Servant of the Lord  Crossbones+   -  Reputation: 12521

Like
0Likes
Like

Posted 23 March 2013 - 11:45 AM

So if I want a function that moves if given an rvalue, and copies if given an lvalue, then I just take by value?
#include <iostream>
#include "Common/Assorted/ConstructionCounter.h"

ConstructionCounter DoSomething(ConstructionCounter instance)
{
return instance;
}

int main(int argc, char *argv[])
{
{
ConstructionCounter instanceA; //One construct, one destruct.
ConstructionCounter instanceB = DoSomething(instanceA); //One copy, one move, two destructs.
ConstructionCounter instanceC = DoSomething(std::move(instanceA)); //Two moves, two destructs.
ConstructionCounter instanceD = DoSomething(ConstructionCounter()); //One construct, one move, two destructs
}

std::cout << "Constructions: " << ConstructionCounter::ConstructorCount << std::endl;
std::cout << "Destructions: " << ConstructionCounter::DestructorCount << std::endl;
std::cout << "Copy Constructs: " << ConstructionCounter::CopyCount << std::endl;
std::cout << "Move Constructs: " << ConstructionCounter::MoveCount << std::endl;

return 0;
}

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS