Jump to content

  • Log In with Google      Sign In   
  • 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.

  • You cannot reply to this topic
3 replies to this topic

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

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.

[Fly with me on Twitter] [Google+] [My broken website]

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]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


Sponsor:

#2 SiCrane   Moderators   -  Reputation: 9328

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.

#3 King Mir   Members   -  Reputation: 1889

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.


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

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.

[Fly with me on Twitter] [Google+] [My broken website]

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]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal





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