*new or new?

C

Cristiano

It is better:
AnyClass &reg=*new AnyClass();
reg.Function();

or:
AnyClass *reg=new AnyClass();
reg->Function();

Thanks
Cristiano
 
V

Victor Bazarov

Cristiano said:
It is better:
AnyClass &reg=*new AnyClass();
reg.Function();

or:
AnyClass *reg=new AnyClass();
reg->Function();

For those two fragments the difference is only in the amount
of storage the program uses. The latter case _allocates_ some
storage for the pointer, and for the former it is unspecified
because it is up to the implementation whether references do
require storage.

Victor
 
P

Peter Koch Larsen

Cristiano said:
It is better:
AnyClass &reg=*new AnyClass();
reg.Function();

or:
AnyClass *reg=new AnyClass();
reg->Function();

Thanks
Cristiano

The first form is obscure. How do you free the memory afterwards? Perhaps
you are confused, having programmed in Java (or C#) before. In this case the
alternatives are:


AnyClass reg;
reg.Function();

or:

AnyClass *reg=new AnyClass();
reg->Function();

If this is what you meant, You should always prefer the first case unless
compelled to do otherwise (and then you should prefer a smart pointer rather
than a raw one).

Kind regards
Peter
 
C

Cristiano

Peter said:
Cristiano said:
It is better:
AnyClass &reg=*new AnyClass();
reg.Function();

or:
AnyClass *reg=new AnyClass();
reg->Function();

The first form is obscure. How do you free the memory afterwards?
Perhaps you are confused, [...]

Confused!? To free the memory you just need delete &reg.
In this case the alternatives are:

AnyClass reg;
reg.Function();

But this form is allocated into the stack (which usually is not too big).
or:

AnyClass *reg=new AnyClass();
reg->Function();

Which is what I wrote above and it is the form that I prefer.

Kind regards
Cristiano
 
J

Jeff Schwab

Of those options, I prefer the first. I do something similar in certain
constructors, e.g.

template< typename T >
class C
{
T& m_t;

public:

C( ):
m_t( *new T )
{ }

~C( )
{
delete &m_t;
}
};

The first form is obscure. How do you free the memory afterwards?
Perhaps you are confused, [...]

I don't know about "obsure..."
Confused!? To free the memory you just need delete &reg.




But this form is allocated into the stack (which usually is not too big).

Unless you have some particular reason to expect stack overflow,
Victor's right. Stack allocation is much faster and simpler than heap
allocation, and it avoids the need to call delete.
 
V

Victor Bazarov

Jeff Schwab said:
Cristiano said:
Peter said:
"Cristiano" <[email protected]> skrev i en meddelelse

It is better:
AnyClass &reg=*new AnyClass();
reg.Function();

or:
AnyClass *reg=new AnyClass();
reg->Function(); [...]
In this case the alternatives are:

AnyClass reg;
reg.Function();


But this form is allocated into the stack (which usually is not too
big).

Unless you have some particular reason to expect stack overflow,
Victor's right. Stack allocation is much faster and simpler than heap
allocation, and it avoids the need to call delete.

You mean, Peter Koch Larsen's right... I'd love to take credit, but can't.
 
J

Jeff Schwab

Victor said:
You mean, Peter Koch Larsen's right... I'd love to take credit, but can't.

D'oh! Your post was right over Peter's in my reader; I should be more
careful. 20 bonus points for honesty, and my apologies to Peter.

-Jeff
 
C

Cy Edmunds

Jeff Schwab said:
Of those options, I prefer the first. I do something similar in certain
constructors, e.g.

template< typename T >
class C
{
T& m_t;

public:

C( ):
m_t( *new T )
{ }

~C( )
{
delete &m_t;
}
};

What is the advantage of this over the more obvious

template< typename T >
class C
{
T *m_t;
public:
C( ) : m_t(new T) { }
~C( ) {delete m_t;}
};

?
The first form is obscure. How do you free the memory afterwards?
Perhaps you are confused, [...]

I don't know about "obsure..."

Seems obscure to me. I don't usually think of a reference as a resource
which needs to be released.

[snip]
 
J

Jeff Schwab

Cy said:
What is the advantage of this over the more obvious

template< typename T >
class C
{
T *m_t;
public:
C( ) : m_t(new T) { }
~C( ) {delete m_t;}
};

?

More obvious to you, maybe, but not to me. :) The advantages are less
typing, better readability when the dynamically allocated object is
used, and the fact that '.' can't be overloaded (so I know exactly what
I'm getting). Mostly, I just think "object.method( )" looks nicer than
"object->method( )".

The first form is obscure. How do you free the memory afterwards?
Perhaps you are confused, [...]

I don't know about "obsure..."


Seems obscure to me. I don't usually think of a reference as a resource
which needs to be released.

[snip]

It's not. The dynamically allocated memory is. What difference does it
make, when you're using an object, how the object was allocated?

-Jeff
 
C

Cy Edmunds

Jeff Schwab said:
More obvious to you, maybe, but not to me. :) The advantages are less
typing, better readability when the dynamically allocated object is
used, and the fact that '.' can't be overloaded (so I know exactly what
I'm getting). Mostly, I just think "object.method( )" looks nicer than
"object->method( )".

Me too. But that has nothing to do with it:

T &method() {return m_t;}

your way or

T &method() {return *m_t;}

mine. Any interface you can implement with a reference you can also
implement with a pointer. Thus the interface semantics are a moot point.

I will give an advantage to storing a pointer: it is closer to the intent of
the program. A pointer is generated in the constructor, stored in the class,
and deleted at destruction time. Converting it to a reference and then back
again just muddies up what is going on, making the program harder to
understand.

But it's a small point. Happy holidays.
The first form is obscure. How do you free the memory afterwards?
Perhaps you are confused, [...]

I don't know about "obsure..."


Seems obscure to me. I don't usually think of a reference as a resource
which needs to be released.

[snip]

It's not. The dynamically allocated memory is. What difference does it
make, when you're using an object, how the object was allocated?

-Jeff
 
N

Nicholas Hounsome

blah blah

You are all off course.
In general (i.e. more complicated class) the only exception safe
implementation is:

template<class T>
class C
{
std::auto_ptr<T> m;

C() : m(new T) {}
}

For one member it doesn't matter much but if you have 2 or more and the
ctors can throw then only auto_ptr will gaurantee that there are no leaks
e.g:

class C
{
T* m1; // or T&
T* m2; // or T&
C() : m1(new T), m2(new T) {}
~C();
};

If the ctor of the second T throws then ~C() will not be called and the
first T will be leaked.
 
P

Peter Koch Larsen

Nicholas Hounsome said:
blah blah

You are all off course.
In general (i.e. more complicated class) the only exception safe
implementation is:

Of course - and i mentioned that in my original reply.
template<class T>
class C
{
std::auto_ptr<T> m;

However, it is by no means certain that a std::auto_ptr will serve your
needs, which is one of the reasons i did not elaborate on that aspect.
C() : m(new T) {}
}

For one member it doesn't matter much but if you have 2 or more and the
ctors can throw then only auto_ptr will gaurantee that there are no leaks

Your std::auto_ptr will not follow the same rules as the reference in the
original post. And now you will no longer be able to use your class as an
element in e.g. a std::vector. I would go for a boost::shared_ptr.
e.g:

class C
{
T* m1; // or T&
T* m2; // or T&
C() : m1(new T), m2(new T) {}
~C();
};

If the ctor of the second T throws then ~C() will not be called and the
first T will be leaked.
Kind regards
Peter
 
C

Cristiano

Jeff said:
Unless you have some particular reason to expect stack overflow,
Victor's right. Stack allocation is much faster and simpler than heap
allocation, and it avoids the need to call delete.

I should use that allocation for the big classes of C++ Builder. To allocate
them, it is suggested to use
TClass *MyClass = new TCLass()
instead of
TClass MyCLass.
(which sometimes doesn't work).

Thank you
Cristiano
 
C

Cy Edmunds

Nicholas Hounsome said:
blah blah

You are all off course.
In general (i.e. more complicated class) the only exception safe
implementation is:

template<class T>
class C
{
std::auto_ptr<T> m;

C() : m(new T) {}
}

For one member it doesn't matter much but if you have 2 or more and the
ctors can throw then only auto_ptr will gaurantee that there are no leaks

No, there are other ways.
e.g:

class C
{
T* m1; // or T&
T* m2; // or T&
C() : m1(new T), m2(new T) {}
~C();
};

If the ctor of the second T throws then ~C() will not be called and the
first T will be leaked.

Classes which contain std::auto_ptr get the strange copy semantics of
std::auto_ptr. That's why I would never put one in a class. For instance:

C x, y;
x = y; // changes x AND y!

This is too weird to let loose on the world. I don't care what the
documentation says.

In the previous discussion we were only considering how to store the
pointer, not the design of a complete class. The Rule of Three tells us that
if a class has a destructor, a copy constructor, or an assignment operator
it almost certainly needs all three. Thus the classes we were talking about
had worse problems than exception safety -- you couldn't even copy one
safely. There are two solutions to this which provide exception safety while
supporting normal copying semantics:

1) include a proper copy constructor and assignment operator
2) wrap the pointer in a reference counted smart pointer and get rid of the
destructor

The first solution is much harder to do correctly than the second, but it
certainly can be done.
 
J

Jeff Schwab

Cristiano said:
I should use that allocation for the big classes of C++ Builder. To allocate
them, it is suggested to use
TClass *MyClass = new TCLass()
instead of
TClass MyCLass.
(which sometimes doesn't work).

It sure sounds like the implementers had a reason to expect overflow. :)
Have you actually seen "TClass MyClass" fail?
 
C

Cristiano

Jeff said:
It sure sounds like the implementers had a reason to expect overflow.
:)
Have you actually seen "TClass MyClass" fail?

No. MyClass doesn't exist.
When I try to compile TRegistry reg I get: "VCL style classes must be
constructed using operator new" and the compiler stops.

Cristiano
 
E

E. Robert Tisdale

Cristiano said:
It is better:
AnyClass &reg=*new AnyClass();
reg.Function();

or:

AnyClass *pReg=new AnyClass();
pReg->Function();

AnyClass reg;
reg.Function();

is best.

But, if you must allocate storage from the free store,
the first is *always* preferred
unless the "reference" must be "reseated" later.
 
N

Nick Hounsome

E. Robert Tisdale said:
AnyClass reg;
reg.Function();

is best.

But, if you must allocate storage from the free store,
the first is *always* preferred

by you.
unless the "reference" must be "reseated" later.

What about freeing the storage?
No delete - leaks.
delete &reg - leaves an invalid reference
 
J

Jeff Schwab

Nick said:
by you.




What about freeing the storage?
No delete - leaks.
delete &reg - leaves an invalid reference

Just as delete pReg leaves a pointer to an invalid address.

It seems to me that the difference between these two notations is mostly
aesthetic. The only "real" difference I see is that -> can be
overloaded, whereas . cannot. Either might be preferable, according to
circumstance.

If somebody can come up with a part of the Standard that prefers one of
these notations to the other, I'll be interested to read it.

-Jeff
 
N

Nick Hounsome

Jeff Schwab said:
Just as delete pReg leaves a pointer to an invalid address.

There is a difference - the pointer can be set to 0 and subsequently tested.
Indeed it is common to write stuff like:
if( !p ) p = new P();
There is no equivalent for references.
It seems to me that the difference between these two notations is mostly
aesthetic. The only "real" difference I see is that -> can be
overloaded, whereas . cannot. Either might be preferable, according to
circumstance.

The advantage of references is the gaurantee (in the absence of people dong
the above) that the reference is valid.
This is very helpful when dealing with analy retentive coding standards that
insist that you check all pointers for null on entry.

One advantage of pointers is that you can put them in an auto_ptr and forget
them. (Of course you could write an equivalent for your references).
Another is that you can use 0 to mean something - either as a parameter when
it usualy means 'use defaults' or as a member when it means 'not yet
initialized'
If somebody can come up with a part of the Standard that prefers one of
these notations to the other, I'll be interested to read it.

I have found a more serious argument: consider

AnyClass& reg=*new DerivedFromAnyClass();

The standard states that the implementation can (implementation defined)
bind to the AnyClass subobject of a temporary copy.
This would obviously be a disaster since the original would leak and delete
&reg would try to deallocate something on the stack.

P.S. The equivalent to
AnyClass& reg=*new AnyClass();
is
AnyClass * const pReg=new AnyClass();
not
AnyClass *pReg=new AnyClass();

Because the latter can be rebound unlike the reference
 

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

Similar Threads

Can't spot source of corruption! 3
Returning by value (here we go again!) 11
AnyClass 11
Newbie question 5
Calling a constructor? 10
New Learner 0
C++ cryptography new library 0
Need Assistance With A Coding Problem 0

Members online

Forum statistics

Threads
474,159
Messages
2,570,883
Members
47,415
Latest member
SharonCran

Latest Threads

Top