473,385 Members | 1,344 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

temporaries and const&

Hi everyone, please consider the following function:-

const int& foo ( const double& d )
{
return d;
}

g++ compiles it with warnings and solaris CC gives error. I want to
know if the code is correct according to the standard ?

/P

Apr 30 '07 #1
13 3934
* dragoncoder:
Hi everyone, please consider the following function:-

const int& foo ( const double& d )
{
return d;
}

g++ compiles it with warnings and solaris CC gives error. I want to
know if the code is correct according to the standard ?
It's technically correct.

In the return expression an "int const&" reference is bound to
(initialized with) a temporary "int" that's initialized with the
"double", which is implicitly converted to int.

However, using the result of a call to foo() yields Undefined Behavior,
because you're returning a reference to a temporary. C++ is like that,
very permissive by default. It cheerfully lets you shoot yourself in
the groin, instead of arresting you[1], if that's what you say you want.

Cheers,

- Alf
Notes:
[1] <url: http://news.bbc.co.uk/1/hi/england/south_yorkshire/3891311.stm>.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Apr 30 '07 #2
dragoncoder wrote:
Hi everyone, please consider the following function:-

const int& foo ( const double& d )
{
return d;
}

g++ compiles it with warnings and solaris CC gives error. I want to
know if the code is correct according to the standard ?
It's "correct", lexically and syntactically. The problem is that
the whole thing is useless because returning by a reference to const
will cause creation of a temporary object, which will survive only
until the end the call to 'foo'. IOW right after the function
returns the temporary object has already been destroyed.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 30 '07 #3
On Apr 30, 1:54 pm, "Alf P. Steinbach" <a...@start.nowrote:
* dragoncoder:
Hi everyone, please consider the following function:-
const int& foo ( const double& d )
{
return d;
}
g++ compiles it with warnings and solaris CC gives error. I want to
know if the code is correct according to the standard ?

It's technically correct.

In the return expression an "int const&" reference is bound to
(initialized with) a temporary "int" that's initialized with the
"double", which is implicitly converted to int.

However, using the result of a call to foo() yields Undefined Behavior,
because you're returning a reference to a temporary. C++ is like that,
very permissive by default. It cheerfully lets you shoot yourself in
the groin, instead of arresting you[1], if that's what you say you want.
Thanks for the response. In the same context, does this code invoke
undefined behaviour ?

#include <iostream>

template <class T1, class T2>
const T1& max ( const T1& a, const T2& b )
{
return ( a b ) ? a : b;
}

int main() {
int i = 20; double d = 40;
std::cout << max ( i, d ) << std::endl;
return 0;
}

Apr 30 '07 #4
* dragoncoder:
>
Thanks for the response. In the same context, does this code invoke
undefined behaviour ?

#include <iostream>

template <class T1, class T2>
const T1& max ( const T1& a, const T2& b )
{
return ( a b ) ? a : b;
}

int main() {
int i = 20; double d = 40;
std::cout << max ( i, d ) << std::endl;
return 0;
}
Yep. It would be less clear-cut if both arguments were "int const&".
I'd have to read the standard's fine print about the ?:-operator to
figure that out, but I think that when the types are identical reference
types it can produce a reference result, thus no UB in that case.

For more information about how to produce a macro-like templated max
function, see Andrei Alexandrescu's "min and max redivivus" article in
DDJ April 2003, <url: http://www.ddj.com/dept/cpp/184403774>.

The standard library's templated max function just puts the burden on
the programmer, and assumes both arguments are the same type.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Apr 30 '07 #5
On Apr 30, 1:38 pm, dragoncoder <pktiw...@gmail.comwrote:
Hi everyone, please consider the following function:-

const int& foo ( const double& d )
{
return d;

}

g++ compiles it with warnings and solaris CC gives error. I want to
know if the code is correct according to the standard ?

/P
Sorry but g++ -pedantic -Wall generates 2 warnings:
warning: converting to 'const int' from 'const double'
warning: returning reference to temporary

You should be using static_cast and returning by value, not be
reference, for obvious reasons.
Even so an integer is an integer and a double a double.


Apr 30 '07 #6
On Apr 30, 2:21 pm, "Alf P. Steinbach" <a...@start.nowrote:
* dragoncoder:


Thanks for the response. In the same context, does this code invoke
undefined behaviour ?
#include <iostream>
template <class T1, class T2>
const T1& max ( const T1& a, const T2& b )
{
return ( a b ) ? a : b;
}
int main() {
int i = 20; double d = 40;
std::cout << max ( i, d ) << std::endl;
return 0;
}

Yep. It would be less clear-cut if both arguments were "int const&".
I'd have to read the standard's fine print about the ?:-operator to
figure that out, but I think that when the types are identical reference
types it can produce a reference result, thus no UB in that case.
I am a bit confused now. Are you saying it is a case of UB because the
temporary is being accessed after the function call ? That being the
case a simple function like below will also invoke UB ? Am I right ?

const int& bar ( ) { return 10; }

std::cout << bar() << std::endl;

Please enlighten me. Thanks again.

Apr 30 '07 #7
* dragoncoder:
On Apr 30, 2:21 pm, "Alf P. Steinbach" <a...@start.nowrote:
>* dragoncoder:


>>Thanks for the response. In the same context, does this code invoke
undefined behaviour ?
#include <iostream>
template <class T1, class T2>
const T1& max ( const T1& a, const T2& b )
{
return ( a b ) ? a : b;
}
int main() {
int i = 20; double d = 40;
std::cout << max ( i, d ) << std::endl;
return 0;
}
Yep. It would be less clear-cut if both arguments were "int const&".
I'd have to read the standard's fine print about the ?:-operator to
figure that out, but I think that when the types are identical reference
types it can produce a reference result, thus no UB in that case.

I am a bit confused now. Are you saying it is a case of UB because the
temporary is being accessed after the function call ?
Yes.

The temporary no longer exists at the point where it's used.

Or, in practice it may still exist, but in practice it may also have
been overwritten.

That being the
case a simple function like below will also invoke UB ? Am I right ?
Yes.

const int& bar ( ) { return 10; }

std::cout << bar() << std::endl;

Please enlighten me.
<url:
http://www.amazon.com/Computer-Parables-Enlightenment-Information-Age/dp/0931137136>.

Hm, I'd better buy that book, and quite a few others!

Can't go on recommending books I've never even read (I only have two C++
books, namely TCPPPL in 1st and 2nd edition, the 3rd edition on
permanent load to someone I don't know, and Modern C++ Design, yet I go
on recommending Accelerated C++, C++ Primer, You Can Do It!, etc.).

Thanks again.
You're welcome.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Apr 30 '07 #8
On Apr 30, 7:38 pm, dragoncoder <pktiw...@gmail.comwrote:
Hi everyone, please consider the following function:-
const int& foo ( const double& d )
{
return d;
}
g++ compiles it with warnings and solaris CC gives error. I want to
know if the code is correct according to the standard ?
Formally, it's undefined behavior if you use the return value in
any way. If you don't use the return value, I'm not 100% sure,
but if you're never going to use the return value, what's the
point?

As undefined behavior, a compiler is not required to give a
message. In addition, in this case, the undefined behavior only
occurs if you actually execute the statement (or maybe only if
you actually use the return value); formally, a compiler is
required to compile the code unless it can prove that the
function will actually be called. (Practically, of course, I
have no problem with a compiler declaring it an error, and
refusing to compile the code. What's the point in compiling a
function that you cannot legally call?)

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 1 '07 #9
On Apr 30, 8:10 pm, dragoncoder <pktiw...@gmail.comwrote:
On Apr 30, 1:54 pm, "Alf P. Steinbach" <a...@start.nowrote:
* dragoncoder:
Hi everyone, please consider the following function:-
const int& foo ( const double& d )
{
return d;
}
g++ compiles it with warnings and solaris CC gives error. I want to
know if the code is correct according to the standard ?
It's technically correct.
I'm not even sure about that. I "think" the intent is that
copying a dangling reference is undefined behavior (since the
intent is that references can be implemented as pointers, and
copying a dangling pointer is undefined behavior). And
formally, you copy the reference in the return statement,
*after* having "destructed" the local variables.

In practice, of course, even on a machine where copying dangling
pointers does cause a crash, it will work, because in practice, the
return value will be moved to its final location (probably a
register) before the memory on the stack is freed. So any
undefined behavior (if there is some) if you don't use the
return value is purely theoretical.
In the return expression an "int const&" reference is bound to
(initialized with) a temporary "int" that's initialized with the
"double", which is implicitly converted to int.
However, using the result of a call to foo() yields Undefined Behavior,
because you're returning a reference to a temporary. C++ is like that,
very permissive by default. It cheerfully lets you shoot yourself in
the groin, instead of arresting you[1], if that's what you say you want.
Thanks for the response. In the same context, does this code invoke
undefined behaviour ?
#include <iostream>
template <class T1, class T2>
const T1& max ( const T1& a, const T2& b )
{
return ( a b ) ? a : b;

}
int main() {
int i = 20; double d = 40;
std::cout << max ( i, d ) << std::endl;
return 0;
}
Yes, although I almost missed it. That's a very bad definition
for max. Try:

template< typename T >
T const&
max( T const& a, T const& b )
{
return a b ? a : b ;
}

You want the type conversion before calling the function, and in
cases of ambiguities like this one, you want the user to
explicitly specify what he wants, and not just automatically
take the type of the first argument.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 1 '07 #10
On Apr 30, 8:21 pm, "Alf P. Steinbach" <a...@start.nowrote:
* dragoncoder:
Thanks for the response. In the same context, does this code invoke
undefined behaviour ?
#include <iostream>
template <class T1, class T2>
const T1& max ( const T1& a, const T2& b )
{
return ( a b ) ? a : b;
}
int main() {
int i = 20; double d = 40;
std::cout << max ( i, d ) << std::endl;
return 0;
}
Yep. It would be less clear-cut if both arguments were "int const&".
I'd have to read the standard's fine print about the ?:-operator to
figure that out, but I think that when the types are identical reference
types it can produce a reference result, thus no UB in that case.
If both types are lvalues, and neither type requires a
conversion, the result is an lvalue. Thus, no temporary.
For more information about how to produce a macro-like templated max
function, see Andrei Alexandrescu's "min and max redivivus" article in
DDJ April 2003, <url:http://www.ddj.com/dept/cpp/184403774>.
The standard library's templated max function just puts the burden on
the programmer, and assumes both arguments are the same type.
Which is really what you want (although I think Andrei's
solution does try to find the best type, for some definition of
best, instead of arbitrarily using the first type).

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 1 '07 #11
On Apr 30, 1:59 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
dragoncoder wrote:
Hi everyone, please consider the following function:-
const int& foo ( const double& d )
{
return d;
}
g++ compiles it with warnings and solaris CC gives error. I want to
know if the code is correct according to the standard ?

It's "correct", lexically and syntactically. The problem is that
the whole thing is useless because returning by a reference to const
will cause creation of a temporary object, which will survive only
until the end the call to 'foo'. IOW right after the function
returns the temporary object has already been destroyed.
I am under the impression that temporaries assigned to const
references are required to live as long as the reference.

However, wrt OP, I happen to know that Sun CC (Studio8) defaults to
non-standard behavior wrt the lifespan of temporaries. By default
temporaries live until the end of the block they are created in.
However, turning on standard behavior (-features=tmplife) is actually
broken because temporaries assigned to const refefrences are destroyed
before the reference is destroyed.

May 1 '07 #12
da********@warpmail.net wrote:
On Apr 30, 1:59 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>dragoncoder wrote:
>>Hi everyone, please consider the following function:-
>>const int& foo ( const double& d )
{
return d;
}
>>g++ compiles it with warnings and solaris CC gives error. I want to
know if the code is correct according to the standard ?

It's "correct", lexically and syntactically. The problem is that
the whole thing is useless because returning by a reference to const
will cause creation of a temporary object, which will survive only
until the end the call to 'foo'. IOW right after the function
returns the temporary object has already been destroyed.

I am under the impression that temporaries assigned to const
references are required to live as long as the reference.
That's correct. But this is one of two special cases mentioned in the
Standard. See 12.2/5, "The temporary bound to the returned value in
a function return statement (6.6.3) persists until the function exits."
[...]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
May 1 '07 #13
On May 1, 7:12 pm, davidru...@warpmail.net wrote:
On Apr 30, 1:59 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
dragoncoder wrote:
Hi everyone, please consider the following function:-
const int& foo ( const double& d )
{
return d;
}
g++ compiles it with warnings and solaris CC gives error. I want to
know if the code is correct according to the standard ?
It's "correct", lexically and syntactically. The problem is that
the whole thing is useless because returning by a reference to const
will cause creation of a temporary object, which will survive only
until the end the call to 'foo'. IOW right after the function
returns the temporary object has already been destroyed.
I am under the impression that temporaries assigned to const
references are required to live as long as the reference.
That's false. A temporary which is used to initialize a const
reference has its lifetime extended (never shorted) to
correspond to that of the const reference it initializes. That
doesn't help here, since the formal semantics of a return
statement are to construct a return value of the correct type,
then destruct all local variables, then *copy* the return value
to where ever return values are returned. (After the return, of
course, the calling code then uses whatever was returned.) The
temporary here is used to initialize this first return value
reference, whose lifetime ends at the end of the function.
However, wrt OP, I happen to know that Sun CC (Studio8)
defaults to non-standard behavior wrt the lifespan of
temporaries. By default temporaries live until the end of the
block they are created in. However, turning on standard
behavior (-features=tmplife) is actually broken because
temporaries assigned to const refefrences are destroyed before
the reference is destroyed.
Funny, I regularly use this option with Sun CC, and I've never
had any problem with it. (On the other hand, it's entirely
possible that I've no code, anywhere, which uses the extended
lifetime. It's only useful in very rare cases.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 2 '07 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: hoox2 | last post by:
void push_front(Node const*& head, int data); Can someone tell me what it means for "const*&"? A reference or a pointer?
20
by: christopher diggins | last post by:
I have heard it is considered good practice to pass function parameters as const& as often as possible, is this true? Is it possible to go overboard? And if so why? Thanks a lot in advance...
12
by: zealotcat | last post by:
template <class T> inline T const& max (T const& a, T const& b) { // if a < b then use b else use a return a<b?b:a; } thanks very much!!
25
by: Victor Bazarov | last post by:
In the project I'm maintaining I've seen two distinct techniques used for returning an object from a function. One is AType function(AType const& arg) { AType retval(arg); // or default...
6
by: p|OtrEk | last post by:
What is practic difference between this two declarations? If i want call my func with func("blah") i could write: 1) func(std::string const& arg1) 2) func(const std::string& arg1) Whats better to...
0
by: tom olson | last post by:
After more searching I found that defining const operators can cause problems with many compilers due to the way it interprets the C++ standard. I removed the const operators from my class and it...
8
by: vsgdp | last post by:
Does this mean (T* const)& (i.e., a reference to a constant pointer to a T). So the pointer is constant but not the object pointed to?
2
by: ek | last post by:
This first example does not work (cannot be overloaded): int& operator()(int a) { // (1) return a; } int const& operator()(int a) { // (2) return a; }
2
by: nassim.bouayad.agha | last post by:
Hello, here is a code snippet showning my problem : template<typename _K> class TClass1 { public: void Process(const _K& arg) const {
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.