[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Problem "taking address of temporary"

Andy Gibbs

11/18/2008 3:53:00 PM

Hello,

I have a problem with the following example code:

#include <stdio.h>

class Test
{
public:
Test(char* str)
{
printf("ctor\n");
_str = str;
}

~Test()
{
printf("dtor\n");
}

char* _str;
};

void Function(const Test* const t)
{
if (t) printf("str=%s\n", t->_str);
else printf("null\n");
}

int main(int argc, char *argv[])
{
printf("test1:\n");
{ Test t("test1"); Function(&t); }

printf("test2:\n");
Function(&Test("test2"));

printf("test3:\n");
Function(0);
}


The problem comes in the line "Function(&Test("test2"));" with the
warning "taking address of temporary". I am using GCC 4.1.2. However, the
code runs as expected with the following output:

test1:
ctor
str=test1
dtor
test2:
ctor
str=test2
dtor
test3
null

The code above demonstrates that the Test object is not destroyed until
after Function is called, so I cannot see why the compiler complains about
this. However, for my actual application, this particular syntax is what I
require in order to keep the code at its most legible, and so I really hope
to find a solution to this warning.

Is there some way I should alter the signature of Function to stop the
warning? Is there a compiler option to ignore this specific warning (e.g.
a #pragma or something)?

Thanks for any help!

Andy


9 Answers

Victor Bazarov

11/18/2008 4:49:00 PM

0

Andy Gibbs wrote:
> I have a problem with the following example code:
>
> #include <stdio.h>
>
> class Test
> {
> public:
> Test(char* str)
> {
> printf("ctor\n");
> _str = str;
> }

This is a bad idea. You're holding onto the address passed to you. You
don't know where it's been, who owns it and how long it's going to still
be valid. In such circumstances my doctor usually says "well, don't do
that!"

>
> ~Test()
> {
> printf("dtor\n");
> }
>
> char* _str;
> };
>
> void Function(const Test* const t)
> {
> if (t) printf("str=%s\n", t->_str);
> else printf("null\n");
> }
>
> int main(int argc, char *argv[])
> {
> printf("test1:\n");
> { Test t("test1"); Function(&t); }

And here you're constructing 't' by giving it a string literal, whose
conversion to 'char*' is only in the language due to the C compatibility
compromise. Don't do that. Switch to using 'std::string'.

>
> printf("test2:\n");
> Function(&Test("test2"));
>
> printf("test3:\n");
> Function(0);
> }
>
>
> The problem comes in the line "Function(&Test("test2"));" with the
> warning "taking address of temporary". I am using GCC 4.1.2. However, the
> code runs as expected with the following output:
>
> test1:
> ctor
> str=test1
> dtor
> test2:
> ctor
> str=test2
> dtor
> test3
> null
>
> The code above demonstrates that the Test object is not destroyed until
> after Function is called, so I cannot see why the compiler complains about
> this.

Because the creators of that compiler thought it would be a bad idea to
take the address of a temporary. Some people think they can retain the
address for future use. The temporary (since any class object is an
lvalue) has a unique address, but it doesn't mean you should use it at
all. The compiler cannot analyse the entire program and understand that
you don't retain the address, that you only use it without exceeding the
lifetime of the referred-to temporary. Compilers are only as smart as
their creators make them. Taking address of a temporary can lead to bad
things. That's why it's a warning and not a hard error.

> However, for my actual application, this particular syntax is what I
> require in order to keep the code at its most legible, and so I really hope
> to find a solution to this warning.

Ignore it. But heed all other warnings, especially from folks here
(wink-wink).

>
> Is there some way I should alter the signature of Function to stop the
> warning?

If you intend to use temporaries, pass them by reference to const. Stop
using naked pointers, they are dangerous. Especially where temporaries
are concerned.

Pay attention to const-correctness as well, it's very important.

> Is there a compiler option to ignore this specific warning (e.g.
> a #pragma or something)?

Probably, but we can't tell you. Pragmas and warnings are compiler-
specific and as such are discussed in the respective compiler
newsgroups, not here.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Pete Becker

11/18/2008 4:50:00 PM

0

On 2008-11-18 10:52:48 -0500, Andy Gibbs <andyg1001@hotmail.co.uk> said:

>
> The problem comes in the line "Function(&Test("test2"));" with the
> warning "taking address of temporary". I am using GCC 4.1.2. However, the
> code runs as expected with the following output:
>
> test1:
> ctor
> str=test1
> dtor
> test2:
> ctor
> str=test2
> dtor
> test3
> null
>
> The code above demonstrates that the Test object is not destroyed until
> after Function is called, so I cannot see why the compiler complains about
> this.

The compiler warns about it because the code takes the address of a
temporary, although there's nothing inherently wrong with doing that.
If you misuse the result you can get in trouble. Apparently the writers
of your compiler thnk that you can't be trusted to use that address
without screwing up.

> However, for my actual application, this particular syntax is what I
> require in order to keep the code at its most legible, and so I really hope
> to find a solution to this warning.

Turn off the warning. Or maybe passing the value by reference instead
of through a pointer would quiet this warning.

>
> Is there some way I should alter the signature of Function to stop the
> warning? Is there a compiler option to ignore this specific warning (e.g.
> a #pragma or something)?
>

Yes, there are compiler switches for this. Check the compiler's documentation.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

James Kanze

11/18/2008 5:24:00 PM

0

On Nov 18, 5:50 pm, Pete Becker <p...@versatilecoding.com> wrote:
> On 2008-11-18 10:52:48 -0500, Andy Gibbs <andyg1...@hotmail.co.uk> said:
> > The problem comes in the line "Function(&Test("test2"));"
> > with the warning "taking address of temporary". I am using
> > GCC 4.1.2. However, the code runs as expected with the
> > following output:

> > test1:
> > ctor
> > str=test1
> > dtor
> > test2:
> > ctor
> > str=test2
> > dtor
> > test3
> > null

> > The code above demonstrates that the Test object is not
> > destroyed until after Function is called, so I cannot see
> > why the compiler complains about this.

> The compiler warns about it because the code takes the address
> of a temporary, although there's nothing inherently wrong with
> doing that.

Has this changed in the latest draft. According to my copy of
the standard (version 1998---out of date, I know), "The
operand [of the unary & operator] shall be an lvalue or a
qualified-id". His expression was &Test("test2"); IMHO, the
compiler generated a warning because it was being laxist.

If I compile his code with Sun CC, I get:
"addrtemp.cc", line 34: Warning, badargtypel2w: String literal
converted to char* in formal argument str in call to Test::Test
(char*).
"addrtemp.cc", line 37: Warning, badargtypel2w: String literal
converted to char* in formal argument str in call to Test::Test
(char*).
"addrtemp.cc", line 37: Error, wantvarname: The "&" operator can
only be applied to a variable or other l-value.
Which is what I'd expect from a good compiler. Curiously
enough, g++ only generates says:
addrtemp.cc: In function 'int main(int, char**)':
addrtemp.cc:37: warning: taking address of temporary
even with -std=c++98 -pedantic (I'd call this a bug), and VC++
doesn't say anything.

> If you misuse the result you can get in trouble. Apparently
> the writers of your compiler thnk that you can't be trusted to
> use that address without screwing up.

Apparently, the writers of his compiler don't care about the
standard. (Nothing new there.) And it's the members of the
stadnards committee who think you can't be trusted. (Or just
wanted to remain compatible with C in this respect.)

--
James Kanze (GABI Software) email:james.kanze@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

Victor Bazarov

11/18/2008 5:54:00 PM

0

James Kanze wrote:
> On Nov 18, 5:50 pm, Pete Becker <p...@versatilecoding.com> wrote:
>> On 2008-11-18 10:52:48 -0500, Andy Gibbs <andyg1...@hotmail.co.uk> said:
>>> The problem comes in the line "Function(&Test("test2"));"
>>> with the warning "taking address of temporary". I am using
>>> GCC 4.1.2. However, the code runs as expected with the
>>> following output:
>
>>> test1:
>>> ctor
>>> str=test1
>>> dtor
>>> test2:
>>> ctor
>>> str=test2
>>> dtor
>>> test3
>>> null
>
>>> The code above demonstrates that the Test object is not
>>> destroyed until after Function is called, so I cannot see
>>> why the compiler complains about this.
>
>> The compiler warns about it because the code takes the address
>> of a temporary, although there's nothing inherently wrong with
>> doing that.
>
> Has this changed in the latest draft. According to my copy of
> the standard (version 1998---out of date, I know), "The
> operand [of the unary & operator] shall be an lvalue or a
> qualified-id". His expression was &Test("test2"); IMHO, the
> compiler generated a warning because it was being laxist.
> [..]

There is an inherent controversy around this. Example:

struct Foo {
Foo(int) {}
Foo& that() { return *this; }
};

int main() {
Foo(42); // expression that yields an rvalue
Foo(42).that(); // expression that is an lvalue
}

How would you explain that? :-) You can't avoid being "laxist" with the
language that contains such pearls.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Andrey Tarasevich

11/18/2008 7:06:00 PM

0

Andy Gibbs wrote:
>
> The problem comes in the line "Function(&Test("test2"));" with the
> warning "taking address of temporary". I am using GCC 4.1.2. However, the
> code runs as expected with the following output:
>
> test1:
> ctor
> str=test1
> dtor
> test2:
> ctor
> str=test2
> dtor
> test3
> null
>
> The code above demonstrates that the Test object is not destroyed until
> after Function is called, so I cannot see why the compiler complains about
> this.

The compiler complains about this because it is _illegal_ in C++ to take
the address of a temporary. Temporary objects are not lvalues in C++,
which means that unary '&' is not applicable to them. Your program is
ill-formed, meaning that the attempt to take address is what is normally
called an "error". Your compiler issues a mere "warning" simply because
it decided to allow you to take the address as a compiler-specific
language extension, but at the same time wants to stick with the
standard requirement to issue a "diagnostic message" in case of an
ill-formed program.

Also, an experiment with the code doesn't really "demonstrate" anything
reliably.

> However, for my actual application, this particular syntax is what I
> require in order to keep the code at its most legible, and so I really hope
> to find a solution to this warning.

I'd recommend you to stick with well-formed code. I.e. stop trying to
get the address of a temporary.

--
Best regards,
Andrey Tarasevich

Andrey Tarasevich

11/18/2008 7:09:00 PM

0

Victor Bazarov wrote:
>
> There is an inherent controversy around this. Example:
>
> struct Foo {
> Foo(int) {}
> Foo& that() { return *this; }
> };
>
> int main() {
> Foo(42); // expression that yields an rvalue
> Foo(42).that(); // expression that is an lvalue
> }
>
> How would you explain that? :-) You can't avoid being "laxist" with the
> language that contains such pearls.
> ...

There's an inherent controversy around everything, if you dig deep
enough. Your example is not really different from, say

const int* addr(const int& i) { return &i; }

int main() {
const int* p = addr(42);
}

You think this is a "pearl"? I'd say this is just a necessary evil one
has to remember about.

--
Best regards,
Andrey Tarasevich

Pete Becker

11/18/2008 9:44:00 PM

0

On 2008-11-18 12:24:01 -0500, James Kanze <james.kanze@gmail.com> said:

> On Nov 18, 5:50 pm, Pete Becker <p...@versatilecoding.com> wrote:
>> On 2008-11-18 10:52:48 -0500, Andy Gibbs <andyg1...@hotmail.co.uk> said:
>>> The problem comes in the line "Function(&Test("test2"));"
>>> with the warning "taking address of temporary". I am using
>>> GCC 4.1.2. However, the code runs as expected with the
>>> following output:
>
>>> test1:
>>> ctor
>>> str=test1
>>> dtor
>>> test2:
>>> ctor
>>> str=test2
>>> dtor
>>> test3
>>> null
>
>>> The code above demonstrates that the Test object is not
>>> destroyed until after Function is called, so I cannot see
>>> why the compiler complains about this.
>
>> The compiler warns about it because the code takes the address
>> of a temporary, although there's nothing inherently wrong with
>> doing that.
>
> Has this changed in the latest draft. According to my copy of
> the standard (version 1998---out of date, I know), "The
> operand [of the unary & operator] shall be an lvalue or a
> qualified-id". His expression was &Test("test2"); IMHO, the
> compiler generated a warning because it was being laxist.

No, it hasn't changed. I was being lax. Thanks for pointing it out.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

James Kanze

11/18/2008 10:57:00 PM

0

On Nov 18, 6:53 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> James Kanze wrote:

[...]
> >> The compiler warns about it because the code takes the
> >> address of a temporary, although there's nothing inherently
> >> wrong with doing that.

> > Has this changed in the latest draft.  According to my copy of
> > the standard (version 1998---out of date, I know), "The
> > operand [of the unary & operator] shall be an lvalue or a
> > qualified-id".  His expression was &Test("test2"); IMHO, the
> > compiler generated a warning because it was being laxist.
> > [..]

> There is an inherent controversy around this.  Example:

>     struct Foo {
>         Foo(int) {}
>         Foo& that() { return *this; }
>     };

>     int main() {
>        Foo(42);        // expression that yields an rvalue
>        Foo(42).that(); // expression that is an lvalue
>     }

> How would you explain that? :-)

I wouldn't try to:-). But the language standard defines a
concept of lvalue and rvalue, or at least insists that they
exist, that certain expressions return lvalues, others rvalues,
and that certain operators require lvalues, others rvalues (and
that there is an lvalue to rvalue conversion---so that in
something like i=j, where both i and j have type int, there is
an implicit conversion involved). The language says that the
expression Test("test1") is an rvalue, and it says that unary &
requires an lvalue, and so be it.

> You can't avoid being "laxist" with the language that contains
> such pearls.

Such "pearls" are probably inevitable as soon as you try to
maintain the distinction between lvalues and rvalues, and also
have real objects. (At one point, I actually suggested that we
drop the concept of lvalue/rvalue completely, and simply state
that all temporaries were considered const. This would have
allowed things like &3, with type int const, but after all, we
allow this indirectly already, if you bind 3 to a const
reference, and then take its address.)

--
James Kanze (GABI Software) email:james.kanze@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

Andy Gibbs

11/19/2008 7:22:00 AM

0

Andy Gibbs wrote:

> Hello,
>
> I have a problem with the following example code:
>
> ...

Hello all,

Thanks for all your comments and recommendations!

Cheers
Andy