C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Question on returning full copies on stack and their referen

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
AB
Guest





PostPosted: Fri Oct 03, 2003 11:42 am    Post subject: Question on returning full copies on stack and their referen Reply with quote



Hello,
I have already googled through this group but could not find any
response to the following scenario. While in a method, a const
reference is created for a full copy of an object that was returned on
the stack. Is this a valid thing to do or not?

Here is some sample code to illustrate the issue:
#include <iostream>
#include <string>
#include <vector>

class X
{
public:
vector<int> getList() { return(vecX); }
vector<int> &getList2() { return(vecX); }

private:
vector<int> vecX;
};

void fn1(X &xinst)
{
xinst.getList2().push_back(1);
xinst.getList2().push_back(2);

const vector<int> &x2=xinst.getList();
for (int i=0; i < x2.size(); ++i) {
cout << "x " << x2[i] << endl;
}
}

int main(void)
{
X *xinst=new X();
fn1(*xinst);
return 0;
}

The code seems to work fine but the question is, is the constant
reference "x2" pointing to anything valid after calling
xinst.getList() or is it just luck of the draw?

Regards,
AB.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Ron
Guest





PostPosted: Sat Oct 04, 2003 8:36 am    Post subject: Re: Question on returning full copies on stack and their ref Reply with quote



Quote:
I have already googled through this group but could not find any
response to the following scenario. While in a method, a const
reference is created for a full copy of an object that was returned on
the stack. Is this a valid thing to do or not?

Here is some sample code to illustrate the issue:
#include <iostream
#include #include
class X
{
public:
vector vector<int> &getList2() { return(vecX); }

private:
vector<int> vecX;
};

void fn1(X &xinst)
{
xinst.getList2().push_back(1);
xinst.getList2().push_back(2);

const vector<int> &x2=xinst.getList();
for (int i=0; i < x2.size(); ++i) {
cout << "x " << x2[i] << endl;
}
}
...
The code seems to work fine but the question is, is the constant
reference "x2" pointing to anything valid after calling
xinst.getList() or is it just luck of the draw?

Your code is OK, but I wouldn't make a habit of it. Ordinarily,
temporaries are destroyed at the end of the full-expression that
creates them. s.12.2(3). However, when you bind a reference to a
temporary, the temporary's lifetime generally is extended to match the
reference's lifetime. s.12.2(5). This occurs when binding a reference
to a function's return value; s.12.2(5) says, "A temporary bound to
the returned value in a function return statement (6.6.3) persists
until the function exits." This is a little inartfully phrased, but
s.12.2(5)'s example clarifies it:

------
class C {
// ...
public:
C();
C(int);
friend C operator+(const C&, const C&);
~C();
};
C obj1;
const C& cr = C(16)+C(23);
C obj2;
....
The temporary T3 bound to the reference cr is destroyed at the end of
cr's lifetime, that is, at the end of the program.
------

-Ron

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Joshua Lehrer
Guest





PostPosted: Sat Oct 04, 2003 8:38 am    Post subject: Re: Question on returning full copies on stack and their ref Reply with quote



[email]alb09439 (AT) hotmail (DOT) com[/email] (AB) wrote in message news:<ffcb4c91.0310021547.730dcb86 (AT) posting (DOT) google.com>...
Quote:
Hello,
I have already googled through this group but could not find any
response to the following scenario. While in a method, a const
reference is created for a full copy of an object that was returned on
the stack. Is this a valid thing to do or not?


This initial value of a refernce to non-const must be an lvalue.

T func();

const T& obj(func()); //ok
const T& obj=func(); //ok, same as above
const T& obj=T(1,2,3); //ok

T& obj=func(); //not ok
T& obj=T(1,2,3); //not ok

Temporary objects returned, either from function calls or by calling
constructors directly, may be bound to const references, but not to
non-const references.

The lifetime of the temporary object is guaranteed to be longer than
the lifetime of the reference to which it is bound.

joshua lehrer
factset research systems
NYSE:FDS

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Le Chaud Lapin
Guest





PostPosted: Sat Oct 04, 2003 8:39 am    Post subject: Re: Question on returning full copies on stack and their ref Reply with quote

[email]alb09439 (AT) hotmail (DOT) com[/email] (AB) wrote in message news:<ffcb4c91.0310021547.730dcb86 (AT) posting (DOT) google.com>...
Quote:
class X
{
public:
vector<int> getList() { return(vecX); }
vector<int> &getList2() { return(vecX); }

private:
vector<int> vecX;
};

void fn1(X &xinst)
{
xinst.getList2().push_back(1);
xinst.getList2().push_back(2);

const vector<int> &x2=xinst.getList();
for (int i=0; i < x2.size(); ++i) {
cout << "x " << x2[i] << endl;
}
}



The code seems to work fine but the question is, is the constant
reference "x2" pointing to anything valid after calling
xinst.getList() or is it just luck of the draw?

Yes.

It is best to think of xinst.getList() "yielding" an object, and that
object getting slammed into another, "nameless" object of equal size
[sizeof(X)] occupying some space specifically reserved for it on the
stack. In this case, x2 happens to refer to that "nameless" stack
object.

-Chaud Lapin-

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Brian McKeever
Guest





PostPosted: Sat Oct 04, 2003 1:53 pm    Post subject: Re: Question on returning full copies on stack and their ref Reply with quote

[email]alb09439 (AT) hotmail (DOT) com[/email] (AB) wrote in message news:<ffcb4c91.0310021547.730dcb86 (AT) posting (DOT) google.com>...
[snip]
Quote:
const vector<int> &x2=xinst.getList();
for (int i=0; i < x2.size(); ++i) {
cout << "x " << x2[i] << endl;
}
[snip]
The code seems to work fine but the question is, is the constant
reference "x2" pointing to anything valid after calling
xinst.getList() or is it just luck of the draw?

Yes, the code is fine. getList() returns a copy of the member
variable. The temporary that is returned is bound to the reference,
which extends its lifetime. If you had just called getList() and not
done anything with the returned vector, the temporary would have been
destroyed immediately. It's a special case to make it work the way
you think it should.

Brian

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Sun Oct 05, 2003 12:40 am    Post subject: Re: Question on returning full copies on stack and their ref Reply with quote

In article <c668c1f8.0310030940.12390bb4 (AT) posting (DOT) google.com>, Ron
<rcrane (AT) ictv (DOT) com> writes
Quote:
Your code is OK, but I wouldn't make a habit of it. Ordinarily,
temporaries are destroyed at the end of the full-expression that
creates them. s.12.2(3). However, when you bind a reference to a
temporary, the temporary's lifetime generally is extended to match the
reference's lifetime. s.12.2(5).

Note that you cannot bind a temporary to a reference but only to a const
reference.


--
Francis Glassborow ACCU
If you are not using up-to-date virus protection you should not be reading
this. Viruses do not just hurt the infected but the whole community.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maciej Sobczak
Guest





PostPosted: Mon Oct 06, 2003 12:50 pm    Post subject: Re: Question on returning full copies on stack and their ref Reply with quote

Hi,

Joshua Lehrer wrote:

Quote:
The lifetime of the temporary object is guaranteed to be longer than
the lifetime of the reference to which it is bound.

Of course, we have to be aware of the following gotcha:

struct A {};
struct B
{
B(const A &a) : ref(a) {}
const A &ref;
};

A fun() { return A(); }

int main()
{
B b(fun());
// b.ref is dangling here
}

Here, the temporary object A() is bound to the const reference in the
B's constructor, *but no longer*. In other words, after the B's
constructor finishes, the temporary can be destroyed and from that time
the b's ref member is a dangling reference.

So - carefully with refs to temps.

--
Maciej Sobczak


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
AB
Guest





PostPosted: Tue Oct 07, 2003 6:13 pm    Post subject: Re: Question on returning full copies on stack and their ref Reply with quote

Maciej Sobczak <maciej (AT) maciejsobczak (DOT) com> wrote

Quote:
Hi,

Joshua Lehrer wrote:

The lifetime of the temporary object is guaranteed to be longer than
the lifetime of the reference to which it is bound.

Of course, we have to be aware of the following gotcha:

struct A {};
struct B
{
B(const A &a) : ref(a) {}
const A &ref;
};

A fun() { return A(); }

int main()
{
B b(fun());
// b.ref is dangling here
}

Here, the temporary object A() is bound to the const reference in the
B's constructor, *but no longer*. In other words, after the B's
constructor finishes, the temporary can be destroyed and from that time
the b's ref member is a dangling reference.

So - carefully with refs to temps.

Hello again,
How about the following example based on your example
above(which is where the original problem occurred):

class C
{
public:
C() { ax=new(fun()); }
A getA() { return(*ax); }
~C() { delete ax; }

private:
A *ax;
}; /* class C */

int main()
{
C *cx=new C();
B bx(cx->getA());
// do some stuff with bx here using its (const A& ref)
delete cx;
}

Does this also cause the dangling reference issue in B that you
mentioned in your previous example?

Regards,
AB.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ron Natalie
Guest





PostPosted: Tue Oct 07, 2003 7:14 pm    Post subject: Re: Question on returning full copies on stack and their ref Reply with quote


"AB" <alb09439 (AT) hotmail (DOT) com> wrote

Quote:
Does this also cause the dangling reference issue in B that you
mentioned in your previous example?

No, as long as the A object is still existant that's fine. Of course your code
is fraught with peril because bx lives longer than *cx. If you declared the
C variable locally it would make it safer:

int main() {
C cx;
B bx(cx->getA());
}
bx will be destructed before cx.

By the way, if you use the example code, make sure you implement the copy constructor
and copy-assignment operator for your C class, because if they ever get invoked, your
class will get trashed.



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Glen Low
Guest





PostPosted: Sat Nov 29, 2003 4:50 pm    Post subject: Re: Question on returning full copies on stack and their ref Reply with quote

Quote:
Of course, we have to be aware of the following gotcha:

struct A {};
struct B
{
B(const A &a) : ref(a) {}
const A &ref;
};

A fun() { return A(); }

int main()
{
B b(fun());
// b.ref is dangling here
}

Here, the temporary object A() is bound to the const reference in the
B's constructor, *but no longer*. In other words, after the B's
constructor finishes, the temporary can be destroyed and from that time
the b's ref member is a dangling reference.

Minor pedantry: it should be "after the statement B b(fun());
completes, the temporary can be destroyed." In your case it is the
same as "after the constructor finishes", but you can also do:

B (fun()).something ();

and the temporary should last until the something completes.

According to 12.2/5, there are two possibilities:

"a temporary bound to a reference member in a constructor's
ctor-initializer (class.base.init) persists until the constructor
exits"

OR

"a temporary bound to a reference parameter in a function call
(expr.call) persists until the completion of the full expression
containing the call"

However in a previous thread discussing this, the consensus was the
first applies to temporaries created within a ctor-initializer, so the
first statement does not apply. Therefore the second must apply, since
a constructor is also a function call.

Some empirical tests on gcc seem to confirm this, but I have yet to
experiment in detail with other compilers.

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.