Hello All,
I have downloaded a recent version of g++ (4.3.2) which provides some
features from C++0x. I've been trying various things with rvalue
references, to see how they behave and get an intuition of what can be
done with them.
It seems to be easy to obtain a reference to a temporary that no
longer exists. Is this expected behavior (and thus UB), or should the
complier produce an error or warning?
If this is UB, could the problem be alleviated by increasing the
lifespan of "rvalue reference temporaries (RRT's)" to the end of the
block where the RRT was created? (Just a thought.)
Below is a program that uses rvalue references to bind temporaries to
references, in a function and a struct.
Thanks,
Derek.
/*********** file.cpp ************/
#include <iostream>
#include <cstring>
using namespace std;
// compiled with g++ (GCC) 4.3.2,
// g++ -Wall -std=c++0x file.cpp
string& Max(string&& a, string&& b)
{
if(a > b)
return a;
else
return b;
}
struct S
{
string&& n;
S(string&& nn):n(nn){}
};
int main()
{
string a = "aaa";
string b = "bbb";
string& m1 = Max(a,b);
string& m2 = Max(a, "ccc");
cout << "1:" << m1 << endl;
cout << "2:" << m2 << endl;
m1 += "?";
m2 += "!";
cout << "3:" << a << endl;
cout << "4:" << b << endl;
string ppp("ppp");
S p(ppp), q("qqq"), r("rrr");
cout << "5:" << p.n << endl;
cout << "6:" << q.n << endl;
cout << "7:" << r.n << endl;
}
/*******************
Output:
1:bbb
2:
3:aaa
4:bbb?!
5:ppp
6:
7:
*******************/
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
derek352 (2)
|
12/11/2008 9:22:33 AM |
|
On 11 dic, 09:22, de...@antiquark.com wrote:
> Hello All,
>
> I have downloaded a recent version of g++ (4.3.2) which provides some
> features from C++0x. I've been trying various things with rvalue
> references, to see how they behave and get an intuition of what can be
> done with them.
>
> It seems to be easy to obtain a reference to a temporary that no
> longer exists. Is this expected behavior (and thus UB), or should the
> complier produce an error or warning?
Yes its easier, but if your type has a move constructor you'd better
return by value rather than by reference if you are in doubt
This was explained in depth here:
http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/99ae7ed3b6b4548e/070e8cc916f7a47b
> If this is UB, could the problem be alleviated by increasing the
> lifespan of "rvalue reference temporaries (RRT's)" to the end of the
> block where the RRT was created? (Just a thought.)
Probably not. If the function is not inlined I think its not possible:
// file1.cpp
string&& weird(string&& a, string&& b)
{
return ((std::rand( ) == 1)? a : b);
}
//file2.cpp
string&& c = weird("a", "b"); // which temporary should have its
lifespan increased?
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Rodrigo
|
12/11/2008 11:59:47 PM
|
|
On 11 d�c, 16:22, de...@antiquark.com wrote:
> string& Max(string&& a, string&& b)
> {
> if(a > b)
> return a;
> else
> return b;
>
> }
If I understand correctly, rvalue to lvalue conversions produces a copy.
Therefore you return a temporary.
Ideally, your compiler should be smart enough to warn about this.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Mathias
|
12/12/2008 6:51:59 PM
|
|
On Dec 11, 11:59 pm, Rodrigo <rcc.d...@gmail.com> wrote:
> This was explained in depth here:http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/...
Thank you.
> Probably not. If the function is not inlined I think its not possible:
>
> // file1.cpp
> string&& weird(string&& a, string&& b)
> {
> return ((std::rand( ) == 1)? a : b);
>
> }
>
> //file2.cpp
> string&& c = weird("a", "b"); // which temporary should have its
> lifespan increased?
How about this hack: any rvalue reference temporary (RRT) will be
converted to a static variable by the compiler? So your example would
be rewritten as:
static string rvalref_temp_1; rvalref_temp_1 = "a";
static string rvalref_temp_2; rvalref_temp_2 = "b";
string && c = weird(rvalref_temp_1, rvalref_temp_2);
In effect, you make the lifespan of RRT's eternal! That would allow
them to be called from within functions too:
string& MoreWeird(string&& a)
{
return weird(a, "lalala");//must increase lifespan of "lalala"
}
This would be rewritten as:
string& MoreWeird(string&& a)
{
static string rvalref_temp_1; rvalref_temp_1 = "lalala";
return weird(a, rvalref_temp_1);
}
It would be nice if this aspect of rvalue references were cleaned up,
it would allow some really concise and useful code, e.g, you could
write a single function:
template<class T>
T& RefToMin(T&& a, T&& b)
{
if(a < b)return a; else return b;
}
That you'd otherwise have to overload because RRT's have a short
lifespan.
Derek.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
derek
|
12/12/2008 6:52:26 PM
|
|
On Dec 11, 10:22 am, de...@antiquark.com wrote:
> Hello All,
>
> I have downloaded a recent version of g++ (4.3.2) which provides some
> features from C++0x. I've been trying various things with rvalue
> references, to see how they behave and get an intuition of what can be
> done with them.
>
> It seems to be easy to obtain a reference to a temporary that no
> longer exists.
Not too surprising. After all, temporaries are both rvalues, and,
well, temporary.
> Is this expected behavior (and thus UB), or should the
> complier produce an error or warning?
Given what you show below, it's expected.
> If this is UB, could the problem be alleviated by increasing the
> lifespan of "rvalue reference temporaries (RRT's)" to the end of the
> block where the RRT was created? (Just a thought.)
I don't think that would be a good idea; it's inconsistent the way
regular references work to begin with.
> Below is a program that uses rvalue references to bind temporaries to
> references, in a function and a struct.
>
> Thanks,
> Derek.
>
> /*********** file.cpp ************/
>
> #include <iostream>
> #include <cstring>
> using namespace std;
>
> // compiled with g++ (GCC) 4.3.2,
> // g++ -Wall -std=c++0x file.cpp
>
> string& Max(string&& a, string&& b)
> {
> if(a > b)
> return a;
> else
> return b;
>
> }
Change all your references above to string const& and you have the
exact same problem.
> struct S
> {
> string&& n;
> S(string&& nn):n(nn){}
>
> };
That looks like it's asking for trouble. Change the references above
to string const& and you have the same problem. I don't think rvalue
references are really doing anything new here.
--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
David
|
12/12/2008 6:52:44 PM
|
|
on Fri Dec 12 2008, derek-AT-antiquark.com wrote:
> How about this hack: any rvalue reference temporary (RRT) will be
> converted to a static variable by the compiler? So your example would
> be rewritten as:
>
> static string rvalref_temp_1; rvalref_temp_1 = "a";
> static string rvalref_temp_2; rvalref_temp_2 = "b";
> string && c = weird(rvalref_temp_1, rvalref_temp_2);
>
> In effect, you make the lifespan of RRT's eternal!
Why not just do that for all temporaries bound to references, while
we're at it? Hmm, it would have to be more than static, though, since
functions can be re-entered. Let's just allocate dynamic memory for all
temporaries, and leak it. Heck, let's do that for all temporaries. Or
all variables. Then, because we'll run out of memory eventually, we can
add garbage collection and no references or pointers will ever dangle.
....;-)'ly yours,
--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
David
|
12/13/2008 4:17:12 PM
|
|
> How about this hack: any rvalue reference temporary (RRT) will be
> converted to a static variable by the compiler?
Using static is not as straightforward. Remember that its shared
between function calls. For example (among other potential issues) you
couldn't do this:
string&& m1 = RefToMin("a", "b");
string&& m2 = RefToMin("c", "d");
> It would be nice if this aspect of rvalue references were cleaned up,
> it would allow some really concise and useful code
I get your idea and I agree it would be nice. However, remember that
the rvalue proposal allows to create move constructors; they can be
potentially as fast as a simple memcpy.
Returning by value (in the general case) will be faster by orders of
magnitude in C++0x than in current C++. Its also safer and you can
receive the function's result by value, avoiding the indirection
references would cause.
Check the google cache of http://home.twcny.rr.com/hinnant/cpp_extensions/STL_benchmarks.html
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Rodrigo
|
12/13/2008 4:18:09 PM
|
|
On Dec 13, 4:17 pm, David Abrahams <d...@boostpro.com> wrote:
> Why not just do that for all temporaries bound to references, while
> we're at it? Hmm, it would have to be more than static, though, since
> functions can be re-entered. Let's just allocate dynamic memory for all
> temporaries, and leak it. Heck, let's do that for all temporaries. Or
> all variables. Then, because we'll run out of memory eventually, we can
> add garbage collection and no references or pointers will ever dangle.
Why not, Java does it! (hah!)
So would you say that rvalue references are more of a technical
extension that isn't really meant for "everyday" programming? For
example, with normal references, I use them all the time and don't
worry about UB because the languages places many restrictions on
them.
Would rvalue references be (in a way) similar to using pointers, in
that you have to make sure you're cognizant of the lifetime of rvalue
reference variables?
Thanks,
Derek.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
derek
|
12/14/2008 8:30:32 PM
|
|
On Dec 14, 9:30 pm, de...@antiquark.com wrote:
>
> So would you say that rvalue references are more of a technical
> extension that isn't really meant for "everyday" programming? For
> example, with normal references, I use them all the time and don't
> worry about UB because the languages places many restrictions on
> them.
>
> Would rvalue references be (in a way) similar to using pointers, in
> that you have to make sure you're cognizant of the lifetime of rvalue
> reference variables?
Not unless you consider today's reference in that category too (I
don't):
class A
{
int i_;
public:
explicit A(int i) : i_(i) {assert(i_ > 0);}
~A() {i_ = 0;}
friend bool operator<(const A& x, const A& y) {return x.i_ < y.i_;}
friend std::ostream& operator<<(std::ostream&& os, const A& a)
{
if (a.i_ > 0)
os << "A = " << a.i_;
else
os << "A is destructed";
return os;
}
};
int main()
{
A a2(2);
const A& ar = std::min(A(1), a2);
std::cout << ar << '\n';
}
You get the same dangling reference problem with this program. No
rvalue reference in sight (not even in the implementation of std::min).
Output:
A is destructed
Copy/paste the above code into your compiler and play with it.
-Howard
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Howard
|
12/15/2008 3:08:13 PM
|
|
on Sun Dec 14 2008, derek-AT-antiquark.com wrote:
> On Dec 13, 4:17 pm, David Abrahams <d...@boostpro.com> wrote:
>> Why not just do that for all temporaries bound to references, while
>> we're at it? Hmm, it would have to be more than static, though, since
>> functions can be re-entered. Let's just allocate dynamic memory for all
>> temporaries, and leak it. Heck, let's do that for all temporaries. Or
>> all variables. Then, because we'll run out of memory eventually, we can
>> add garbage collection and no references or pointers will ever dangle.
>
> Why not, Java does it! (hah!)
>
> So would you say that rvalue references are more of a technical
> extension that isn't really meant for "everyday" programming?
No; I think everyone who writes classes will want to define move ctor
and move assignment.
> For example, with normal references, I use them all the time and don't
> worry about UB because the languages places many restrictions on them.
My point is that the language places all the same lifetime restrictions
on regular references, so you have no more reason to fear dangling
rvalue refs than you do to fear dangling references-to-const, since
they'll both bind liberally to temporaries.
X&& a = some_rvalue_expression; // lifetime of a extends to end-of-block
X const& b = some_rvalue_expression; // ditto for b
> Would rvalue references be (in a way) similar to using pointers, in
> that you have to make sure you're cognizant of the lifetime of rvalue
> reference variables?
Yeah, just like any other reference.
--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
David
|
12/15/2008 3:12:43 PM
|
|
de...@antiquark.com wrote:
>
> string& Max(string&& a, string&& b)
> {
> if(a > b)
> return a;
> else
> return b;
> }
>
After all the posts in this thread, I still don't see how this
function could possibly compile, or why it's a good idea to have it
even if it does. As Dave Abrahams said, it's just like
const string& Max(const string& a, const string& b)
{
return (a > b) ? a : b;
}
If you pass in temporaries, you have a dangling reference. Nothing new
with rvalue references here.
Sebastian
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
wasti
|
12/17/2008 7:11:59 PM
|
|
On 18 d�c, 02:11, wasti.r...@gmx.net wrote:
> After all the posts in this thread, I still don't see how this
> function could possibly compile, or why it's a good idea to have it
> even if it does. As Dave Abrahams said, it's just like
>
> const string& Max(const string& a, const string& b)
> {
> return (a > b) ? a : b;
>
> }
This does compile.
It will only issue a warning if your compiler is smart, I doubt it's
mandated.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Mathias
|
12/18/2008 6:02:18 PM
|
|
|
11 Replies
98 Views
(page loaded in 1.717 seconds)
Similiar Articles: Bad use of stringstream temporary? - comp.lang.c++Simple: undefined behaviour. The object created ... step by step, and over > time -- to understand rvalue references and move semantics as I > work to get on ... Neatest way to get the end pointer? - comp.lang.c... www.c-faq.com/> (can anyone find a more explicit reference?). ... And here's UB in action: muntyan@munt10:/tmp$ cat ... iso_c_binding - comp.lang.fortran I am trying to get a simple ... Using regex's in Awk across linebreaks... - comp.lang.awk ...But the 'simple' nature of this task so far hasn't helped ... BTU/HR-SQFT-F) E1 Flr (UB.W2.I1 ... Regular Expressions Reference - Basic Syntax... by the ... Nonlinear curve fit fails to converge - comp.soft-sys.matlab ...Can you point me to any references for partitioned least ... If I could get MatLab to reliably fit with a sigmoid ... LB = [-Inf ymin xmin 0 1/1023]; % 2^(1024) = Inf UB ... Create Multiple Users on Solaris 10 - comp.unix.solarisIt is easy to write a small PAM ap that you could put ... df <userid>" Yes please post the script for future reference. ... Enter class prefix(es) (e.g.: ua ub uc) EOF echo -n ... fmincon vs lsqnonlin - comp.soft-sys.matlab... nonlinear constraints, could you please set up a simple ... because the further away (more global) you get in ... Options Reference :: Argument and Options Reference ... strndup: RFC - comp.compilers.lccYour comment references "n characters", but defines a ... Joe Wright "Everything should be made as simple as ... re: a hypothetical compiler flag "-warn-on-UB ... How to check whether malloc has allocated memory properly in case ...... way: http://www.mindspring.com/~pfilandr/C/get ... all that means, verbatim from the MS Fortran reference ... in theory even fetching or comparing them would be UB ... Const constructor - comp.lang.c++.moderated... ones by never using the nice, handy, easy ... type's semantics (pointer or reference?). > My argument is that you get a ... its argument as an lvalue or an rvalue to ... Examples of C++ in Safety Critical Systems - comp.lang.c++ ...http://www.ctas.arc.nasa.gov/ is good reference for a start. ... behavior in C++. thread programming in C is simple, but ... far as I know freeing memory created on stack is UB. C++11 - Wikipedia, the free encyclopediaMake C++ easy to teach and to learn without removing any utility needed by ... kind of performance benefit, either of memory or of computational speed. Rvalue references ... A Brief Introduction to Rvalue ReferencesFrom a casual programmer's perspective, what we get from rvalue references is more ... Rvalue references offer a simple, scalable solution to this problem: template <class ... 7/11/2012 11:43:59 AM
|