Understanding temporary objects / taking address

H

Henning Hasemann

I have a function which gets the adress of an object as argument.
It does some comparsion with the object's contents and then returns.
no Reference or pointer to the object is stored or will be used after
the function has returned.

Say the function whould be named f and the objects class whould be T
it'll look like this:

bool f(T* thing) {
return thing->foobar == 5; // Just a stupid example
}

When I now write a piece of code like this:

bool yesorno = f(&T(77));

I get a warning because I take the address of a temporary object.
Im not sure if this is okay or not here.
Does the object live long enough so f can do its operations on it?

Is it generally a good idea to to such things?
Or should I create an extra local variable which holds T(77)?
(As I will have lots of these calls that whould be unhandy as I use
different subclasses of T and you can Imagine using new and delete for
every call whuld be even unhandier.)

TIA
Henning
 
D

Daniel T.

Henning Hasemann said:
I have a function which gets the adress of an object as argument.
It does some comparsion with the object's contents and then returns.
no Reference or pointer to the object is stored or will be used after
the function has returned.

Say the function whould be named f and the objects class whould be T
it'll look like this:

bool f(T* thing) {
return thing->foobar == 5; // Just a stupid example
}

When I now write a piece of code like this:

bool yesorno = f(&T(77));

I get a warning because I take the address of a temporary object.
Im not sure if this is okay or not here.
Does the object live long enough so f can do its operations on it?

Is it generally a good idea to to such things?
Or should I create an extra local variable which holds T(77)?
(As I will have lots of these calls that whould be unhandy as I use
different subclasses of T and you can Imagine using new and delete for
every call whuld be even unhandier.)

Try changing 'f' to:

bool f( const T* thing );
 
H

Howard

Henning Hasemann said:
I have a function which gets the adress of an object as argument.
It does some comparsion with the object's contents and then returns.
no Reference or pointer to the object is stored or will be used after
the function has returned.

Say the function whould be named f and the objects class whould be T
it'll look like this:

bool f(T* thing) {
return thing->foobar == 5; // Just a stupid example
}

When I now write a piece of code like this:

bool yesorno = f(&T(77));

I get a warning because I take the address of a temporary object.
Im not sure if this is okay or not here.
Does the object live long enough so f can do its operations on it?

Is it generally a good idea to to such things?
Or should I create an extra local variable which holds T(77)?
(As I will have lots of these calls that whould be unhandy as I use
different subclasses of T and you can Imagine using new and delete for
every call whuld be even unhandier.)

I'd prefer to use a const reference as the parameter, myself. That lets you
pass a temporary object fine, with no warnings, (and also handles the
polymorphism correctly, just like a pointer). I only use pointers if I have
to.

-Howard
 
F

Frederick Gotham

Henning Hasemann posted:

Say the function whould be named f and the objects class whould be T
it'll look like this:

bool f(T* thing) {
return thing->foobar == 5; // Just a stupid example
}

When I now write a piece of code like this:

bool yesorno = f(&T(77));

I get a warning because I take the address of a temporary object.
Im not sure if this is okay or not here.


That warning should be an error.

A temporary, nameless object is an R-value. You can't take the address of
a R-value.

If you really want to pass the address of a temporary to a function, try
this:

class ArbitraryClass {
public:
int a;
int b;

ArbitraryClass() : a(1), b(2) {}
};

bool Func( const ArbitraryClass *p )
{
return p->a == p->b;
}

template<class T>
const T *AdrsTmp( const T &temp ) { return &temp; }


int main()
{
Func( AdrsTmp( ArbitraryClass() ) );
}


A temporary lives on until the end of the statement; so the temporary in
the above code gets killed at the end of the semi-colon in "main".

I wonder what people would think if I rewrote "AdrsTmp" like as follows:

template<class T>
T *AdrsTmp( const T &temp ) { return const_cast<T*>(&temp); }


We know that it's pefectly okay to cast away constness if the object in
question is in fact non-const. The temporary in "main" is non-const --
that's for sure. However... is the "AdrsTmp" function free to create
another temporary when it takes its argument, rather than work with the
temporary provided by main... ?
 
H

Henning Hasemann

Howard said:
I'd prefer to use a const reference as the parameter, myself. That lets you
pass a temporary object fine, with no warnings, (and also handles the
polymorphism correctly, just like a pointer). I only use pointers if I have
to.

In this case I have to, as f actually is the contains() method of a
set-template-class and the template Parameter is a pointer type but
could be a non-pointer type as well.

I think Daniel T.'s solution with using a const pointer was what I was
looking for.

Thanks you 2.

Henning
 
H

Henning Hasemann

Frederick said:
Henning Hasemann posted:
A temporary lives on until the end of the statement; so the temporary in
the above code gets killed at the end of the semi-colon in "main".

Hmm.
Shouldnt this be long enough then? At the end of the semicolon Func has
returned, so I got what I needed, or?

I think I half-way understood your wrapper but (still) not exactly why
it is necessary.
If it is such a problem to give away the adress of a temporary, is there
a better way in my case?

Maybe I should tell a bit more od what Im doing. The function I talk
about is the contains-Method of a template-class for a set (Yes I know
of STL, there are reasons for implementing my own).

It looks roughly like this:

template<class T>
class MySet {
public:
// ...
bool contains(const T item) const {
// look at item and return true if
// we have something that is considered to be equal
// ...
}
};

The problematic case is the one, where T is a pointer-type.
As I put different subclasses of T into this set and often look if a
certain item is contained a (to the caller of contains()) local variable
is as unpleasant as creating and deleting objects for each contains() on
the heap.

Henning
 
F

Frederick Gotham

Henning Hasemann posted:
Hmm.
Shouldnt this be long enough then? At the end of the semicolon Func
has returned, so I got what I needed, or?


Yes, exactly.

I think I half-way understood your wrapper but (still) not exactly why
it is necessary.
If it is such a problem to give away the adress of a temporary, is
there a better way in my case?


Well you can continue on with what you're doing, i.e. just stick the
"address of" operator before a nameless temporary:

&ArbitraryClass()

but the C++ Standard forbids this, because you're taking the address of
an R-value. Your compiler is being lenient by letting you do it.

My own code however is perfectly Standard-compliant, because I don't take
the address of an R-value. (Once the object gets bound to a const
reference, you can use the const reference as an L-value).

It's sort of like walking to the checkout with your wife, aiming to buy 6
packets of Aspirin. In line with the Laws of the Land, the cashier
informs you that he can only sell you a maximum of 3 packets, so you tell
him "That's fine", and you just buy 3 packets. Having finalised the
transaction, you then hand the rest of the money to your wife, and she
buys another 3 packets of Aspirin. Sure, it isn't exactly how things are
supposed to work, but by going through the formalities, you haven't
broken the rules.

Think of my template function as your wife ; )
 
H

Henning Hasemann

Frederick said:
Henning Hasemann posted:
but the C++ Standard forbids this, because you're taking the address of
an R-value. Your compiler is being lenient by letting you do it.

Ah okay.
That surprises me a bit though. As I use "g++ (GCC) 3.3.6" with -ansi I
thought it whould be already very strict.
It's sort of like walking to the checkout with your wife, aiming to buy 6
packets of Aspirin. In line with the Laws of the Land, the cashier
informs you that he can only sell you a maximum of 3 packets, so you tell
him "That's fine", and you just buy 3 packets. Having finalised the
transaction, you then hand the rest of the money to your wife, and she
buys another 3 packets of Aspirin. Sure, it isn't exactly how things are
supposed to work, but by going through the formalities, you haven't
broken the rules.

Think of my template function as your wife ; )

Well okay, i finally got the point :)

I'll just leave it the dirty way for now and consider to use your
"adapter" or something else when theres time, fortunately the warning
will remind me sometimes of this.

Thanks for you time :)

Henning
 
R

Roland Pibinger

In this case I have to, as f actually is the contains() method of a
set-template-class and the template Parameter is a pointer type but
could be a non-pointer type as well.

If you have to use pointers (which is not actually clear from your
answer) you should handle pointers appropriately:

bool f (const T* thing) {
return thing && thing->foobar == 5; // Just a stupid example
}

Best wishes,
Roland Pibinger
 
F

Frederick Gotham

Henning Hasemann posted:
I'll just leave it the dirty way for now and consider to use your
"adapter" or something else when theres time, fortunately the warning
will remind me sometimes of this.


Of course, you could use a simple static_cast:


#include <string>

void Func( const std::string * );

int main()
{
Func( &static_cast<const std::string &>( std::string() ) );
}
 
R

Ron Natalie

Henning said:
bool yesorno = f(&T(77));

I get a warning because I take the address of a temporary object.
Im not sure if this is okay or not here.
Does the object live long enough so f can do its operations on it?

It's not OK to apply & to a non-lvalue. The language says unary-&
gets applied to an lvalue (for simple pointers) or a qualified-id
(for poitner to member).
 
R

Ron Natalie

Daniel said:
Try changing 'f' to:

bool f( const T* thing );

How does that help. The error is not in the call to f() but
in the illegal application of unary& to an rvalue.
 
R

Ron Natalie

Henning said:
In this case I have to, as f actually is the contains() method of a
set-template-class and the template Parameter is a pointer type but
could be a non-pointer type as well.

I think Daniel T.'s solution with using a const pointer was what I was
looking for.
No it's not. It's just as wrong as you had before.
 
M

mangesh

Hi ,
u have writtten " The temporary in "main" is non-const -- that's for
sure. "
Is constantness of temporary object compiler dependent ? Because
somewhere on
net i remember reading that temporary object created by compiler are
constant , but i can't recall name of compiler .

Regards ,
Mangesh Sawant .
 
I

Ian Collins

mangesh wrote:

Please don't top post and use gibberish such as 'u'.
Frederick Gotham wrote:
Hi ,
u have writtten " The temporary in "main" is non-const -- that's for
sure. "
Is constantness of temporary object compiler dependent ? Because
somewhere on
net i remember reading that temporary object created by compiler are
constant , but i can't recall name of compiler .
No, the temporary is an rvalue. It can be assigned to a const
reference, but as a value, you can take it's address. All the wrapper
does is assign it to a const reference and take the address of the
reference.

A bit like:

const int& i = 42;

const int* p = &i;

42 is an rvalue, so you can assign it to a const reference, but you
couldn't take its address.
 
D

Daniel T.

Ron Natalie said:
How does that help. The error is not in the call to f() but
in the illegal application of unary& to an rvalue.

It doesn't. Sorry, I was wrong to suggest it.
 
F

Frederick Gotham

mangesh posted:

Hi , u have writtten " The temporary in "main" is non-const -- that's
for sure. " Is constantness of temporary object compiler dependent ?
Because somewhere on net i remember reading that temporary object
created by compiler are constant , but i can't recall name of compiler
.

And I'm glad you can't remember the name of any such compiler.

Let's start off with writing a very simple class which has a member
function which comes in two flavours: The const flavour, and the non-
const flavour.

#include <iostream>

class Arb {
public:

int a;


void Method()
{
a = 7;

std::cout << "The NON-const method was called.\n";
}

void Method() const
{
std::cout << "The CONST method was called.\n";
}


};


Now let's make two typedef's:

typedef Arb NonConstArb;
typedef Arb const ConstArb;


And now let's create two nameless temporaries, one which we intend to be
const, and the other which we intend to be non-const:


int main()
{
NonConstArb();

ConstArb();
}


And now let's invoke our member function upon each of them and see what
happens:


int main()
{
NonConstArb().Method();

ConstArb().Method();
}


I hope the output pleases you.
 

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

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top