I cannot see the need for auto_ptr?!

A

Alf P. Steinbach

Yes, but returning a pointer from foo is a bad progamming practice.
Why don't you just say that auto_ptr is deprecated ?

Each of your sentences parse as english, but neither is meaningful
to me (as far as I know it's never been regarded as bad practice to
return pointers from functions, and as far as I know std::auto_ptr is
not deprecated and has not been suggested for deprecation), and
furthermore, to me they seem mutually contradictory.

What is it you're trying to say?
 
K

Karl Heinz Buchegger

Yes, but returning a pointer from foo is a bad progamming practice.

Says who?
Sometimes you don't have a choice.
Why don't you just say that auto_ptr is deprecated ?

You are concentrating too much on returning pointers.

void bar( int Type )
{
Obj* pObj;

pObj = Factory.CreateObject( Type );

// do something

// object no longer needed, delete it.

delete pObj;
}

Now lets say, that the part // do something is rather complicated and there
is a chance that things might go wrong. You insert some tests and do a return.
But when doing so you must not forget do delete the object given to you
from the factory.


void bar( int Type )
{
Obj* pObj;

pObj = Factory.CreateObject( Type );

// do something
...
if( SomeTest ) {
delete pObj;
return;
}

if( SomeOtherTest ) {
...
while( ... ) {
if( AThirdTest )
return;
}
}
// object no longer needed, delete it.

delete pObj;
}

So you see the big? Deep inside the while, there is an if which returns. It happened
to me, that I forgot to delete pObj, because I am human :)

An auto_ptr saves me from all of this. I don't need to remember to delete pObj, it
is done automatically for me. For the very same reason that you use vector instead
of dynamically allocated arrays, you use an auto_ptr when you must use a pointer, to
free yourself from human errors and to easen maintenance (who says that this test
was there in the first place. It could have been added weeks later).
 
K

Karl Heinz Buchegger

And that's exactly the problem.


Why dynamic allocations in exceptions sensitive code ?

Every code is exception sensitive, except when written explicitly otherwise.
auto_ptr *is* a tool for taking care of exceptions.
 
R

Rob Williscroft

lilburne wrote in
[snip]
Returning large objects on the stack is a worse idea.

// performance killer
vector<Point3D> calculate_some_geometry()
{

vector<Point3D> geometry;

// do something that adds lots of points to geometry

return geometry;
}

std::vector< T > is not a large object typicaly its the size of
3 pointers (12 bytes on my machine). The T's that it containes
are held in storage provided by std::allocator< T > which in turn
get its storage from operator new(), which allocates memory from
free storage aka the heap.

Note also the above example should benefit from NRVO so it should
perform as well as ( and some times better than ) this:

void calculate_some_geometry( vector<Point3D> &geometry )
{
// do something that adds lots of points to geometry
}

The situation in wich it can perform better is:

vector<Point3D> geometry( calculate_some_geometry() );

There is no array version of std::auto_ptr<>, but then we have
std::vector<> so we don't need it :).

Rob.
 
G

Guest

Each of your sentences parse as english, but neither is meaningful
to me (as far as I know it's never been regarded as bad practice to
return pointers from functions, and as far as I know std::auto_ptr is
not deprecated and has not been suggested for deprecation), and
furthermore, to me they seem mutually contradictory.

What is it you're trying to say?

Hi,
A little bit more to parse. Look at the original post. Instead of dynamic
allocation of a single object hold by an auto_ptr we could always use an
automatic variable, maybe inside a template.
auto_ptr holds a single object, the code that uses it does not really use
polymorphizm - because the object is single.
Template is better solution then auto_ptr, also much faster.
 
T

Thore B. Karlsen

A little bit more to parse. Look at the original post. Instead of dynamic
allocation of a single object hold by an auto_ptr we could always use an
automatic variable, maybe inside a template.
auto_ptr holds a single object, the code that uses it does not really use
polymorphizm - because the object is single.
Template is better solution then auto_ptr, also much faster.

This makes even less sense! A template to hold an automatic variable?
auto_ptr does not use polymorphism? What? What?

Are you seriously saying that you can't think of a SINGLE time when you
might want to use auto_ptr or a similar smart pointer class?
 
G

Guest

Every code is exception sensitive, except when written explicitly
otherwise.
auto_ptr *is* a tool for taking care of exceptions.

Yes, but the code doesn't neccesery have to use dynamic allocation.
 
T

tom_usenet

Hello,

I realise that I just dont get this, but I cannot see the need for auto_ptr.
As far as I have read, it means that if you create an object using an
auto_ptr, instead of a raw pointer, then the object will get cleaned up when
the method/function ends. Isn't this what happens if you just declare an
object without using a pointer at all? Aren't these examples the same (I
know they will not be, but I am hoping someone may explain to me what I am
missing here!):

void f()
{
T t;
t.SomeFunc();
} // cleanup when function ends

void f()
{
auto_ptr<T> pt(new T);
pt->SomeFunc();
} // cleanup when function ends

Wish I could see what is going on here!

Use auto_ptr when you want to transfer ownership of pointers around in
an exception safe way. e.g.

struct Foo
{
void transferBase(Base* subelement);
//...
};

vs.

struct Foo
{
void transferBase(auto_ptr<Base> subelement);
//...
};

The second version enforces the transferral of ownership in an
exception safe manner.

Tom
 
K

Karl Heinz Buchegger

Yes, but the code doesn't neccesery have to use dynamic allocation.

True.
But in case it has to, auto_ptr is there to help.

I am with you that dynamic allocations should be kept to
a minimum. But in real world programs it is often necessary
to have them and to deal with pointers. Eg. object factories
wouldn't be possible without them in C++.
 
L

lilburne

I am not getting it. Either your calculate_some_geometry() may fail or not.
If it fails you need a copy , if it doesn't you don't.

Not if you have a pointer. You just replace the pointer no
extra copy required.
 
L

lilburne

Rob said:
lilburne wrote in
[snip]

Returning large objects on the stack is a worse idea.

// performance killer
vector<Point3D> calculate_some_geometry()
{

vector<Point3D> geometry;

// do something that adds lots of points to geometry

return geometry;
}


std::vector< T > is not a large object typicaly its the size of
3 pointers (12 bytes on my machine). The T's that it containes
are held in storage provided by std::allocator< T > which in turn
get its storage from operator new(), which allocates memory from
free storage aka the heap.

Note also the above example should benefit from NRVO so it should
perform as well as ( and some times better than ) this:

The amount of data that std::vector may hold can be very
large, you really don't want to be copying it. Example
500,000 points is quite typical in CADCAM applications, you
do not want to be copying that amount of data about, if you
can possibly help it.

Also each time std:vector has to resize, the current data
gets copied, you have to have enough contigous memory to
hold the new size, and in the worst case half the space is
unused. Also as the internal buffer grows you are likely to
end up with a fragmented memory map.
 
R

Rob Williscroft

lilburne wrote in
Rob said:
lilburne wrote in
[snip]

Returning large objects on the stack is a worse idea.
[snip]
std::vector< T > is not a large object typicaly its the size of
3 pointers (12 bytes on my machine). The T's that it containes
are held in storage provided by std::allocator< T > which in turn
get its storage from operator new(), which allocates memory from
free storage aka the heap.

Note also the above example should benefit from NRVO so it should
perform as well as ( and some times better than ) this:

The amount of data that std::vector may hold can be very
large, you really don't want to be copying it. Example
500,000 points is quite typical in CADCAM applications, you
do not want to be copying that amount of data about, if you
can possibly help it.

None of that makes std::vector<> a "large object on the stack".

Also with (N)RVO, return by value and construction completely
by-passes the copy constructor, so it is a sutible way to
create a std::vector<>, no matter how many points it has.
This may not suit the way you code, but that doesn't make
all return by value (even of "large" objects) a bad idea.

Rob.
 
L

lilburne

Rob said:
lilburne wrote in


None of that makes std::vector<> a "large object on the stack".

Also with (N)RVO, return by value and construction completely
by-passes the copy constructor, so it is a sutible way to
create a std::vector<>, no matter how many points it has.

Avoiding a default constructor by return value optimization
is of minimal use when the underlaying result is the copying
of a Mb of data. If one stuffs 100,000 3D points into a
vector the data it holds is over 2Mb. When the vector is
returned, whether or not 12 bytes are physically transferred
on the stack or not, ultimately over 2Mb of data is copied
into the receiving object, not just 12 bytes.
 
R

Rob Williscroft

lilburne wrote in
Avoiding a default constructor by return value optimization

That isn't what RVO does.
is of minimal use when the underlaying result is the copying
of a Mb of data. If one stuffs 100,000 3D points into a
vector the data it holds is over 2Mb. When the vector is
returned, whether or not 12 bytes are physically transferred
on the stack or not, ultimately over 2Mb of data is copied
into the receiving object, not just 12 bytes.

Not in this case:

std::vector< int > create()
{
std::vector< int > nrv;
// populate ...
return nrv;
}

int main()
{
std::vector< int > res( create() );
}

Assuming you have a compiler that support NRVO, there is NO
copying of a std::vector< int >.

How it can work the address of the yet-to-be-constructed res is
passed as a hidden argument to create(), create() constructs res
(it's local nrv is an alias for main's res) populates res/nrv
and return's. No copying.


Rob.
 
N

Niklas Borson

Hi,
A little bit more to parse. Look at the original post. Instead of dynamic
allocation of a single object hold by an auto_ptr we could always use an
automatic variable, maybe inside a template.

To rephrase the OP's question, "Why would you ever want to use auto_ptr
when you could just create an automatic variable and return it by value?"
There are several possible answers:

1. The class might be expensive to copy.
2. The class might not be copyable at all.
3. The class might be designed so that it can only be
created on the heap (e.g., using a factory).
4. The class might be used polymorphically.

Note that the NRVA might compensate for #1, but since it is an optimisation
you can't count on it. In any case, it won't compensate for #2 since a copy
constructor must still be accessible even if it is elided.
auto_ptr holds a single object, the code that uses it does not really use
polymorphizm - because the object is single.

This doesn't follow. There are many cases where a single object is
used polymorphically. For example, consider any function that takes a
basic_ostream parameter.
Template is better solution then auto_ptr, also much faster.

It seems to me that they solve different problems.
 
L

lilburne

Rob said:
lilburne wrote in




Assuming you have a compiler that support NRVO, there is NO
copying of a std::vector< int >.

That is one big assumption. Besides code that relies on a
compiler optimization is a wee bit suspect. Supposing the
NVRO compiler decides not to optimize? Since 1992 I've seen
the g++ compiler optimize the same code differently in each
version, and mostly it has become more cautious in its
optimizations as bugs have been discovered.
 
R

Rob Williscroft

lilburne wrote in
That is one big assumption. Besides code that relies on a
compiler optimization is a wee bit suspect. Supposing the
NVRO compiler decides not to optimize?

The assumption above was on my part. There is no assumtion on your
part you either have a compiler that suports NVRO or you don't. If
you don't get a compiler that does.

NVRO is the common name for a set of language features, technicaly not
an optimisation as it's allowed to break the as-if rule. It is nothing
to do with a compilers optimizer and a supporting compiler will do it
with all optimizations turned off. Though maybe it would have a switch
to turn it off (like many compilers have for RTTI etc) but I can't think
why it would.

Rob.
 
L

lilburne

Rob said:
lilburne wrote in



The assumption above was on my part. There is no assumtion on your
part you either have a compiler that suports NVRO or you don't. If
you don't get a compiler that does.

NVRO is the common name for a set of language features, technicaly not
an optimisation as it's allowed to break the as-if rule. It is nothing
to do with a compilers optimizer and a supporting compiler will do it
with all optimizations turned off. Though maybe it would have a switch
to turn it off (like many compilers have for RTTI etc) but I can't think
why it would.

Well I thought "maybe he isn't clueless", and decided to put
it to the test. I tried gcc 3.3.1 which is supposed to have
NVRO and you know what ... it copies the data.
 
?

=?iso-8859-1?Q?Juli=E1n?= Albo

lilburne escribió:
Well I thought "maybe he isn't clueless", and decided to put
it to the test. I tried gcc 3.3.1 which is supposed to have
NVRO and you know what ... it copies the data.

I make this little test with 3.3 20030226

#include <iostream>

using std::cout;
using std::endl;

class A
{
public:
A ()
{
cout << "Constructor" << endl;
}
A (const A &)
{
cout << "Copy constructor" << endl;
}
};

A f ()
{
return A ();
}

int main ()
{
cout << "a" << endl;
A a = f ();
cout << "b" << endl;
A b= a;
}

The output is:

a
Constructor
b
Copy constructor

No copy construction for a, and the copy constructor clearly works.

How do you tested in gcc 3.3.1?

Regards.
 

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


Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,144
Latest member
KetoBaseReviews
Top