What do you expect this to print?

S

Steven T. Hatton

What should I expect the following code to print? Is it defined in the
Standard? What does it produce for you? I was kind of surprised by what
GCC 4.0.2 made of it.

#include <string>
#include <iostream>

typedef std::string object;

class arrow{
public:
arrow(object& domain_
,object& codomain_
,const std::string& name_)
:_domain(domain_)
,_codomain(codomain_)
,_name(name_)
{
std::cout << _name << std::endl;
}

object domain(){ return _domain; }
object codomain(){ return _codomain; }

operator object () { return _codomain; }

std::eek:stream& print(std::eek:stream& out) const {
return out<<_domain<<"--"<<_name<<"->"<<_codomain;
}

private:
object _domain;
object _codomain;
const std::string& _name;
};

std::eek:stream& operator<<(std::eek:stream& out, const arrow& a ){
return a.print(out);
}

int main(){
object a("a");
object b("b");
arrow f(a,b,"f");
std::cout << f << std::endl;
}
 
P

paulius-maruska

Steven said:
What should I expect the following code to print? Is it defined in the
Standard? What does it produce for you? I was kind of surprised by what
GCC 4.0.2 made of it.
As expected, it outputs:
f
a--->b

However, if you change _name member from const std::string& to
std::string it produces:
f
a--f->b

(Again - as expected).
 
A

Alf P. Steinbach

* Steven T. Hatton:
What should I expect the following code to print? Is it defined in the
Standard?

It's Undefined Behavior.

What does it produce for you? I was kind of surprised by what
GCC 4.0.2 made of it.

#include <string>
#include <iostream>

typedef std::string object;

class arrow{
public:
arrow(object& domain_
,object& codomain_
,const std::string& name_)
:_domain(domain_)
,_codomain(codomain_)
,_name(name_)

Binding a reference to a temporary is only OK as long as that temporary
persists.

{
std::cout << _name << std::endl;
}

object domain(){ return _domain; }
object codomain(){ return _codomain; }

operator object () { return _codomain; }

std::eek:stream& print(std::eek:stream& out) const {
return out<<_domain<<"--"<<_name<<"->"<<_codomain;
}

private:
object _domain;
object _codomain;
const std::string& _name;

Remove the 'const' and especially the '&' and you'll be okay.

Possibly you thought that binding a reference to const to a temporary
magically makes that temporary persist.

That's only for a local reference, and it's actually a bit more subtle
(formally a new temporary is created with lifetime extended to the scope of
the reference, and the initializer rvalue is copied to that temporary).
 
Z

Zara

What should I expect the following code to print? Is it defined in the
Standard? What does it produce for you? I was kind of surprised by what
GCC 4.0.2 made of it.
(...)
class arrow{
public:
arrow(object& domain_
,object& codomain_
,const std::string& name_)
:_domain(domain_)
,_codomain(codomain_)
,_name(name_)
{
std::cout << _name << std::endl;
}
(...)
private:
object _domain;
object _codomain;
const std::string& _name;
};
(...)

int main(){
object a("a");
object b("b");
arrow f(a,b,"f");
std::cout << f << std::endl;
}

The result is undefined.

You are initialising a temporary string with "f", then assigning a
reference to it (_name). After f ceration, the temporary disappears
(=is not longer valid), and you have an invalid reference.
 
S

Steven T. Hatton

Alf said:
* Steven T. Hatton:

It's Undefined Behavior.



Binding a reference to a temporary is only OK as long as that temporary
persists.

As I suspected.
Remove the 'const' and especially the '&' and you'll be okay.

Indeed.
Possibly you thought that binding a reference to const to a temporary
magically makes that temporary persist.

I really hadn't thought about it until I did it. It was just toy code I was
using to try and reason out some obtuse mathematical language.
That's only for a local reference, and it's actually a bit more subtle
(formally a new temporary is created with lifetime extended to the scope
of the reference, and the initializer rvalue is copied to that temporary).

I guess I had intuitively expected the temporary to outlive its scope in
that case. I'm glad I messed it up in that situation rather than in
serious code. I suspect that behavior varies from compiler (version) to
compiler (version).
 
S

Steven T. Hatton

paulius-maruska said:
As expected, it outputs:
f
a--->b

Is the first 'f' required by law? I suspect not. That is to say, I suspect
the scope of the temporary is actually the argument list. Even that may be
overstating things since I don't believe the value of the actual parameter
has a specified state vis-a-vis other actual parameters in the same
function call.
 

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

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,735
Latest member
HikmatRamazanov

Latest Threads

Top