# reference and const-reference question

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

## 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 on other sites
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 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 on other sites
Quote:
 Original post by SiCraneMaulingMonkey isn't quite right.

Thanks for clarifying, this is what I get for self-teaching...

##### Share on other sites
Quote:
Original post by MaulingMonkey
Quote:
 Original post by SiCraneMaulingMonkey 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.

1. 1
2. 2
Rutin
19
3. 3
4. 4
5. 5

• 9
• 9
• 9
• 14
• 12
• ### Forum Statistics

• Total Topics
633301
• Total Posts
3011268
• ### Who's Online (See full list)

There are no registered users currently online

×