Is this legal? assigning return value to a const ref?

F

flopbucket

Hi,

Is this legal?

std::string foo()
{
std::string xyz = "FOO";

return xyz;
}


void bar()
{
const std::string s = foo();

// ... use s now
}

Does that force the xyz std::string that was returned (copy
constructed I assume) to be bound the the const reference and stay
around? Or is it going ot of scope since the object itself is not
being stored someplace explicitly named?

Thanks
 
F

flopbucket

Hi,

OP here, in bar() it should be a const reference:

std::string foo()
{
std::string xyz = "FOO";
return xyz;
}


void bar()
{
const std::string& s = foo();

// ... use s now

}
 
V

Victor Bazarov

flopbucket said:
Is this legal?

Yes (even considering your correction in the other post).
std::string foo()
{
std::string xyz = "FOO";

return xyz;
}


void bar()
{
const std::string s = foo();

// ... use s now
}

Does that force the xyz std::string that was returned (copy
constructed I assume) to be bound the the const reference and stay
around?

Yes, it does. The object returned from 'foo' is called "a temporary".
It's OK to bind a const reference to it.
Or is it going ot of scope since the object itself is not
being stored someplace explicitly named?

No, it isn't.

V
 
J

James Kanze

OP here, in bar() it should be a const reference:
std::string foo()
{
std::string xyz = "FOO";
return xyz;
}
void bar()
{
const std::string& s = foo();
// ... use s now
}

It's perfectly legal, but what's the point in using the const
reference (preferably written "std::string const&") rather than
a value?
 
F

flopbucket

It's perfectly legal, but what's the point in using the const
reference (preferably written "std::string const&") rather than
a value?

Well, in this particular case, the code was returning a reference to a
member variable. The internals of the class had to change for other
reasons and I was wondering if it was safe to just leave the calling
code as is, which used a const reference.

Thanks
 
V

Victor Bazarov

flopbucket said:
Well, in this particular case, the code was returning a reference to a
member variable. The internals of the class had to change for other
reasons and I was wondering if it was safe to just leave the calling
code as is, which used a const reference.

It sounds like the code you posted didn't actually reflect what the
real code was doing. Perhaps you want to give your question another
shot and post the code before refactoring and after just to see if
somebody sees any problems in it.

V
 
G

Guest

Well, in this particular case, the code was returning a reference to a
member variable.

No, it did not, foo() was declared to return a string, not a reference
to a string. That means that a copy will be created and you will then
make the const reference refer to that copy.
The internals of the class had to change for other
reasons and I was wondering if it was safe to just leave the calling
code as is, which used a const reference.

The code as you posted it is safe. However if you change foo() to return
a reference to a string instead you will have problems.
 
J

James Kanze

On 2007-10-30 14:55, flopbucket wrote:
No, it did not, foo() was declared to return a string, not a reference
to a string. That means that a copy will be created and you will then
make the const reference refer to that copy.

I think he meant that it was in the past, but that it doesn't
any more---that in his actual code, foo() was a member function
that used to return a reference to a member variable, but now
returns a value.

In such cases, I'm still sceptical about the reference at the
call site. If I use a reference as a local variable, it's
because I want it to concretely refer to something; I want the
value to change, for example, if the member variable of the
class changes its value. Otherwise, I'll use a value. So the
fact that the function used to return a reference rather than a
value wasn't incidental (an "optimization"); it was an essential
part of the semantics of the class, which I was counting on.
The change in the class has probably broken my code.
 
J

Jim Langston

OP here, in bar() it should be a const reference:
std::string foo()
{
std::string xyz = "FOO";
return xyz;
}
void bar()
{
const std::string& s = foo();
// ... use s now
}

It's perfectly legal, but what's the point in using the const
reference (preferably written "std::string const&") rather than
a value?

==================

I tested this, and the output of the following program is indeed
One Two Unknown

#include <vector>
#include <iostream>
#include <string>

std::string Foo( int Val )
{
switch (Val)
{
case 1:
return "One";
break;
case 2:
return "Two";
break;
default:
return "Unknown";
break;
}

}

int main()
{
const std::string& One = Foo(1);
const std::string& Two = Foo(2);
const std::string& Three = Foo(3);

std::cout << One << " " << Two << " " << Three << "\n";
}

My question is, what is the lifetime of the returned string? The lifetime
of the references? I understand that normally the lifetime of a temporary
variable returned by a function is the statement it is called on, yet the
std::strings returned by Foo is beyond this.

Where do things std::strings reside, in what variable? I had always thought
that a reference was just a glorified pointer, but this code seems to
indicate more than this. The compiler seems to treat the std::strings
returned by Foo as being owned by the variables One, Two and Three, even
though they are references.

Dang, I thought I actually was starting to understand C++ yet there is
always something that throws me a suprise.
 
G

Guest

It's perfectly legal, but what's the point in using the const
reference (preferably written "std::string const&") rather than
a value?

==================

I tested this, and the output of the following program is indeed
One Two Unknown

#include <vector>
#include <iostream>
#include <string>

std::string Foo( int Val )
{
switch (Val)
{
case 1:
return "One";
break;
case 2:
return "Two";
break;
default:
return "Unknown";
break;
}

}

int main()
{
const std::string& One = Foo(1);
const std::string& Two = Foo(2);
const std::string& Three = Foo(3);

std::cout << One << " " << Two << " " << Three << "\n";
}

My question is, what is the lifetime of the returned string? The lifetime
of the references? I understand that normally the lifetime of a temporary
variable returned by a function is the statement it is called on, yet the
std::strings returned by Foo is beyond this.

Yes, the temporary lives as long as the reference.
Where do things std::strings reside, in what variable? I had always thought
that a reference was just a glorified pointer, but this code seems to
indicate more than this. The compiler seems to treat the std::strings
returned by Foo as being owned by the variables One, Two and Three, even
though they are references.

My guess would be that, since the standard does not talk much about the
implementation of references, in this case the compiler simply creates
three strings on the stack, and the variables One, Two and Three refers
to them. In other words the code generated is the same as though One,
Two, and Three were const strings and not references.
 
A

alexandrebfarias

It's perfectly legal, but what's the point in using the const
reference (preferably written "std::string const&") rather than
a value?

==================

I tested this, and the output of the following program is indeed
One Two Unknown

#include <vector>
#include <iostream>
#include <string>

std::string Foo( int Val )
{
switch (Val)
{
case 1:
return "One";
break;
case 2:
return "Two";
break;
default:
return "Unknown";
break;
}

}

int main()
{
const std::string& One = Foo(1);
const std::string& Two = Foo(2);
const std::string& Three = Foo(3);

std::cout << One << " " << Two << " " << Three << "\n";

}

My question is, what is the lifetime of the returned string? The lifetime
of the references? I understand that normally the lifetime of a temporary
variable returned by a function is the statement it is called on, yet the
std::strings returned by Foo is beyond this.

Where do things std::strings reside, in what variable? I had always thought
that a reference was just a glorified pointer, but this code seems to
indicate more than this. The compiler seems to treat the std::strings
returned by Foo as being owned by the variables One, Two and Three, even
though they are references.

Dang, I thought I actually was starting to understand C++ yet there is
always something that throws me a suprise.

"References to variables and references to constants are distinguished
because the introduction of
a temporary in the case of the variable is highly errorprone;
an assignment to the variable would
become an assignment to the - soon to disappear - temporary. No such
problem exists for references
to constants, and references to constants are often important as
function arguments."
TC++PL §5.5 P98
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top