Jump to content
  • Advertisement
Sign in to follow this  

reference and const-reference question

This topic is 4708 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

consider the following code:
class X {
};

X f() 
{
	return X(); 
}
void g1(X& x) 
{}
void g2(const X& x) 
{}

int main()
{
	g1(f());
	g2(f());

	return 0;
}
I know that reference to a local object is bad. But function g2() is successfully compiled while g1() not. Why ?

Share this post


Link to post
Share on other sites
Advertisement
RETURNING a reference to a local object is bad. Accepting a local object by reference is OK (well, usually - storing the reference in a class of unspecified scope - e.g. newed - is bad mojo too).

Here's what's happening:

f() returns a temporary class by value, X. Because it's a temporary, it's considered constant. g1(f()) fails to compile because you're trying to have a reference to a non constant (in other words, a reference to a mutable object) when the temporary is constant (not mutable).

Basically, it's to catch against weird things like this which don't make sense:

int f() {
return 4;
}

void g1( int & i ) {
i = 5;
}

g1( f() ); //what does this do?


If you don't need to actually modify i, then you simply make g1 accept a reference to a constant:

void int f() {
return 4;
}

void g1( const int & i ) {
std::cout << i << std::endl;
}

g1( f() ); //this prints out 4

Share this post


Link to post
Share on other sites
MaulingMonkey isn't quite right. The problem is that f() returns an r-value and the type X doesn't define an implicit conversion to an l-value compatible with an X reference.

To clarify: In C++ everything is either an r-value or an l-value. When you return an object of class type by value from a function, the returned object is considered to be an r-value. If you have a r-value you can only bind a non-volatile const reference to it, unless the class type defines a conversion to a compatible l-value, like a reference. For example, if X was instead defined like:

class X {
public:
operator X &() { return *this; }
};

Then both function calls should compile since the X type defined an implicit conversion to an l-value. Keep in mind that this conversion operator is non-const. This works because temporaries are not necessarily const. Consider this code:

class X {
public:
void not_const(void) { std::cout << "non const function" << std::endl; }
};

X f() {
return X();
}

int main(int, char **) {
f().not_const();

return 0;
}

This shows more explicitly that a non-const function can be called on a temporary object.

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
Quote:
Original post by SiCrane
MaulingMonkey isn't quite right.

Thanks for clarifying, this is what I get for self-teaching...
I thought your explanations were both great.
Newbies often don't have a clue what an l-value or r-value is though anyway.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!