473,387 Members | 1,374 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,387 software developers and data experts.

I cannot see the need for auto_ptr?!

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!

Jamie.
Jul 19 '05 #1
45 2978
Jamie Burns wrote:
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!


What is required is that the object T is destructed when it
is no longer used and the memory it occupied is returned to
the system. With stack based objects (your first example)
this happens automatically when the object goes out of
scope, but with heap based objects (your second example)
this doesn't occur when a bare pointer goes out of scope.
auto_ptr being a stack based object gets destroyed
automatically, and in the process destroys the heap based
object T that the auto_ptr contains.

Jul 19 '05 #2
OK, so maybe I don't get why you wouldn't just allocate T on the stack? Is
that a bad thing to do? Why go out of your way to allocate on the heap if it
requires this type of attention to cleanup?

Jamie.

"lilburne" <li******@godzilla.net> wrote in message
news:bm************@ID-203936.news.uni-berlin.de...
Jamie Burns wrote:
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!


What is required is that the object T is destructed when it
is no longer used and the memory it occupied is returned to
the system. With stack based objects (your first example)
this happens automatically when the object goes out of
scope, but with heap based objects (your second example)
this doesn't occur when a bare pointer goes out of scope.
auto_ptr being a stack based object gets destroyed
automatically, and in the process destroys the heap based
object T that the auto_ptr contains.

Jul 19 '05 #3
On Sun, 19 Oct 2003 22:00:22 +0100, "Jamie Burns" <se*****@email.com>
wrote:
OK, so maybe I don't get why you wouldn't just allocate T on the stack?
Because you want it to live longer than it would on the stack.
Is that a bad thing to do? Why go out of your way to allocate on the heap if
it requires this type of attention to cleanup?


Because it is very often the right thing to do.

--
Be seeing you.
Jul 19 '05 #4
But if I want it to live longer, surely I wouldn't be using an auto_ptr in
the first place (as it won't live past the end of the function that created
it) ?!

This is what I cannot grasp.

In terms of lifetime, T on the stack, and an auto_ptr<T> on the heap are the
same, no?

If so, that just leaves "Because it is very often the right thing to do",
which whilst I am sure is a sincere opinion, doesn't help me to understand.

:o(

Jamie.

"Thore B. Karlsen" <si*@6581.com> wrote in message
news:9v********************************@4ax.com...
On Sun, 19 Oct 2003 22:00:22 +0100, "Jamie Burns" <se*****@email.com>
wrote:
OK, so maybe I don't get why you wouldn't just allocate T on the stack?


Because you want it to live longer than it would on the stack.
Is that a bad thing to do? Why go out of your way to allocate on the heap ifit requires this type of attention to cleanup?


Because it is very often the right thing to do.

--
Be seeing you.

Jul 19 '05 #5
Jamie Burns wrote:
But if I want it to live longer, surely I wouldn't be using an auto_ptr in
the first place (as it won't live past the end of the function that created
it) ?!
Correct in general but you may want to return one, or you
may have to take ownership of a bare pointer returned from
some thing else.
This is what I cannot grasp.


Sometimes you have no option but to create something on the
heap (say the object is very big)
Jul 19 '05 #6
On Sun, 19 Oct 2003 21:40:55 +0100, Jamie Burns <se*****@email.com> wrote:
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!

Jamie.


You are right, auto_pointer is unnecessary.
One reason to use dynamic allocation is to allocate array of the size
known at the run time. std::vector deals with it.
Second reason could be to create an object which polymorphic type is known
at the run time. Then we could use :
template <class Type> type_dependent_code(Type *p) {
Type data;
data.SomeFunc(); };
void f() {
determine the TYPE;
type_dependent_code(static_cast<TYPE*>(0));
};
Returning pointer to dynamically allocated object is not a good idea
anyway.

--
grzegorz
Jul 19 '05 #7
gr**********@pacbell.net wrote:


Returning pointer to dynamically allocated object is not a good idea
anyway.


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;
}

Jul 19 '05 #8
On Sun, 19 Oct 2003 22:20:42 +0100, "Jamie Burns" <se*****@email.com>
wrote:
But if I want it to live longer, surely I wouldn't be using an auto_ptr in
the first place (as it won't live past the end of the function that created
it) ?!

This is what I cannot grasp.

In terms of lifetime, T on the stack, and an auto_ptr<T> on the heap are the
same, no?


Yes, but you can return the auto_ptr, in effect just returning a pointer
instead of a copy-constructed object which might be expensive or (as is
often the case) impossible, or just not the right thing to do. Or you
can have a big object that is only allocated when it's needed, but whose
lifetime is longer than the scope you're in. Or you can take ownership
of an existing raw pointer and have auto_ptr wrap it and deal with
deallocating it.

If you don't understand why it's necessary, don't worry about it. You
will immediately see its utility once you start writing programs that
are sufficiently complex.

--
Be seeing you.
Jul 19 '05 #9
On Sun, 19 Oct 2003 22:58:39 +0100, lilburne <li******@godzilla.net> wrote:
gr**********@pacbell.net wrote:


Returning pointer to dynamically allocated object is not a good idea
anyway.


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;
}


void calculate_some_geometry(vector<Point3D>& v);

--
grzegorz
Jul 19 '05 #10
Jamie Burns <se*****@email.com> wrote:
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!):


The mechanism by which an auto_ptr ``transfers ownership'' to the
receiving call site makes it a very worthy addition to a C++ developer's
toolchest. (In particular, but realizing that threads are not defined
by the C++ language (hence the parens), it makes it easy to create a
pointer to an object in a routine that ``hands it off'' to a detached
thread).

Here's a toy example of the power afforded by auto_ptr. Note that the
call site need not be concerned with the destruction...that gets
handled when ``f()'' goes out of scope:

=========================== [ cut ] ===================================

#include <cassert>
#include <memory>

using namespace std;

struct C {
C(): i(42) {}
int i;
};

static void f(auto_ptr<C> p)
{
assert(p->i == 42);
assert(p.get());
}

int main()
{
auto_ptr<C> p(new C);

assert(p->i == 42);
assert(p.get());
f(p);
assert(!p.get());
}
Jul 19 '05 #11
gr**********@pacbell.net wrote:


void calculate_some_geometry(vector<Point3D>& v);


Prefered solution, but presupposes that the data's final
resting place is already determined.

Jul 19 '05 #12
On Mon, 20 Oct 2003 00:38:02 +0100, lilburne <li******@godzilla.net> wrote:
gr**********@pacbell.net wrote:


void calculate_some_geometry(vector<Point3D>& v);


Prefered solution, but presupposes that the data's final resting place is
already determined.


That's what i would do with the big data, wouldn't you ?

--
grzegorz
Jul 19 '05 #13
On Sun, 19 Oct 2003 22:50:56 GMT, Bob Nelson <bn*****@nelsonbe.com> wrote:
Jamie Burns <se*****@email.com> wrote:
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!):


The mechanism by which an auto_ptr ``transfers ownership'' to the
receiving call site makes it a very worthy addition to a C++ developer's
toolchest. (In particular, but realizing that threads are not defined
by the C++ language (hence the parens), it makes it easy to create a
pointer to an object in a routine that ``hands it off'' to a detached
thread).


But the idea of creating an object in a routine that hands it of to a
detached thread is not a good idea to start with.
Maybe if reference counted but transfering ownership , under threat ,
maybe.
Point is that the shared resources that are the source of the object
are limited. Owning resources that are shared ?
this was possible in 16 bit dos, maybe not so bad after all.

--
grzegorz
Jul 19 '05 #14
On Sun, 19 Oct 2003 21:40:55 +0100, "Jamie Burns" <se*****@email.com> wrote:
I realise that I just dont get this, but I cannot see the need for auto_ptr.


Ah, well, isn't that in the FAQ?

Checking...

Nope, not all, but the FAQ does explain the merits of std::auto_ptr in the
presence of exceptions,
<url: http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.4>.

Okay, here goes, "std::auto_ptr for ze novice", by yours truly.

std::auto_ptr is currently the only example in the standard library of a
"smart pointer":
A "smart pointer" is an object that encapsulates a pointer and provides
all the operations that the encapsulated pointer has, plus, it provides
automatic deallocation.
The scheme used by std::auto_ptr is very basic: it transfers _ownership_
on assignment and copy construction (the last through a horrible hack).
If a std::auto_ptr object goes out of scope or is otherwise destroyed,
it will deallocate the object it's got a pointer to if and only it
currently owns that object. So as soon as you put a pointer into a
std::auto_ptr you know the pointed-to object will be deallocated sooner
or later; later, if you keep assigning that std::auto_ptr to other
std::auto_ptr's, thus transferring ownership of the object.

Now this is very useful for some oft-occurring situations. Say, for example,
that you want to return a largish object from a function. One way is

LargeObject* foo()
{
return new LargeObject();
}

But this is very unsafe, for who's gonna deallocate that object? There's
nothing about foo that indicates this. Some novice might write

void bar()
{
LargeObject* p = foo();

p->doTheFandango();
}

forgetting to deallocate the object, while a programmer with a year or two
of experience might write

void bar()
{
LargeObject* p = foo();

p->doTheFandango();
delete p;
}

forgetting that 'doTheFandango' might throw an exception, in which case
the object is not deallocated.

If, instead, you design 'foo' as
std::auto_ptr<LargeObject> foo()
{
return new LargeObject();
}

then whoever uses that function has to actively try to _avoid_ proper
deallocation in order to mess things up. The most natural is to write
client code like
void bar()
{
std::auto_ptr<LargeObject> p = foo();

p->doTheFandango();
}

where the call to 'foo' transfers ownership up to the local
std::auto_ptr in 'bar', which guarantees deallocation even if, as Murphy
guarantees will happen, 'doTheFandango' throws an exception.

Jul 19 '05 #15
gr**********@pacbell.net wrote:
On Mon, 20 Oct 2003 00:38:02 +0100, lilburne <li******@godzilla.net> wrote:
gr**********@pacbell.net wrote:


void calculate_some_geometry(vector<Point3D>& v);


Prefered solution, but presupposes that the data's final resting place
is already determined.


That's what i would do with the big data, wouldn't you ?


Not always, and I definitely wouldn't use a vector to store
it either.

You can get away with the reference if you know where the
data is going to end up, but say for example that
calculate_some_geometry() is destructive and may fail,
you'll want to do the calculation and only if it is OK
replace the original data. Taking over a pointer avoids a
final copy.
Jul 19 '05 #16
On Mon, 20 Oct 2003 01:32:05 +0100, lilburne <li******@godzilla.net> wrote:
gr**********@pacbell.net wrote:
You can get away with the reference if you know where the data is going
to end up, but say for example that calculate_some_geometry() is
destructive and may fail, you'll want to do the calculation and only if
it is OK replace the original data. Taking over a pointer avoids a final
copy.


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.
So does it or doesn't it , probably this question doesn't belong here
because - as std says - it's undefined.

--
grzegorz
Jul 19 '05 #17
In article <bm******************@news.demon.co.uk>,
"Jamie Burns" <se*****@email.com> wrote:
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!


Imho, one of the best uses of auto_ptr is to ease making some other
operation exception safe. For example consider:

#include <memory>

template <class T>
class X
{
public:
explicit X(T* ptr);
private:
int* int_data_;
class T* ptr_;
};

template <class T>
X<T>::X(T* ptr)
{
std::auto_ptr<T> hold(ptr);
int_data_ = new int(1);
ptr_ = hold.release();
}

Here the semantics are that X<T> constructs with a T*, and retains
ownership of that pointer no matter what. In addition to retaining
ownership of the T*, X must also acquire some other resource at
construction time. Whether the construciton of X succeeds, or fails
with an exception being thrown, the T* must be managed, not leaked.

So the X(T*) constructor first establishes ownership of the passed in
ptr with an auto_ptr. This is a no-throw operation, guaranteed to
succeed. Now the constructor goes about its other business. If
anything following throws an exception, the local auto_ptr destructor
insures that the T* is properly cleaned up. After construction is
complete, the X officially takes ownership of the T* by transferring it
from the auto_ptr.

-Howard
Jul 19 '05 #18
On Mon, 20 Oct 2003 00:18:47 GMT, Alf P. Steinbach <al***@start.no> wrote:
On Sun, 19 Oct 2003 21:40:55 +0100, "Jamie Burns" <se*****@email.com>
wrote:
I realise that I just dont get this, but I cannot see the need for
auto_ptr.
Ah, well, isn't that in the FAQ?

Checking...

Nope, not all, but the FAQ does explain the merits of std::auto_ptr in
the
presence of exceptions,
<url: http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.4>.

Okay, here goes, "std::auto_ptr for ze novice", by yours truly.

std::auto_ptr is currently the only example in the standard library of a
"smart pointer":


void bar()
{
std::auto_ptr<LargeObject> p = foo();

p->doTheFandango();
}

where the call to 'foo' transfers ownership up to the local
std::auto_ptr in 'bar', which guarantees deallocation even if, as Murphy
guarantees will happen, 'doTheFandango' throws an exception.


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

--
grzegorz
Jul 19 '05 #19
On Mon, 20 Oct 2003 02:11:56 GMT, Howard Hinnant <hi*****@metrowerks.com>
wrote:

So the X(T*) constructor first establishes ownership of the passed in ptr
with an auto_ptr. This is a no-throw operation, guaranteed to succeed.
Now the constructor goes about its other business. If anything following
throws an exception, the local auto_ptr destructor insures that the T* is
properly cleaned up. After construction is complete, the X officially
takes ownership of the T* by transferring it from the auto_ptr.
And that's exactly the problem.

-Howard

Why dynamic allocations in exceptions sensitive code ?

--
grzegorz
Jul 19 '05 #20
On Mon, 20 Oct 2003 04:03:09 GMT, gr**********@pacbell.net wrote:

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?

Jul 19 '05 #21


gr**********@pacbell.net wrote:

void bar()
{
std::auto_ptr<LargeObject> p = foo();

p->doTheFandango();
}

where the call to 'foo' transfers ownership up to the local
std::auto_ptr in 'bar', which guarantees deallocation even if, as Murphy
guarantees will happen, 'doTheFandango' throws an exception.
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).

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 19 '05 #22


gr**********@pacbell.net wrote:

On Mon, 20 Oct 2003 02:11:56 GMT, Howard Hinnant <hi*****@metrowerks.com>
wrote:
So the X(T*) constructor first establishes ownership of the passed in ptr
with an auto_ptr. This is a no-throw operation, guaranteed to succeed.
Now the constructor goes about its other business. If anything following
throws an exception, the local auto_ptr destructor insures that the T* is
properly cleaned up. After construction is complete, the X officially
takes ownership of the T* by transferring it from the auto_ptr.


And that's exactly the problem.

-Howard


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.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 19 '05 #23
lilburne wrote in news:bm************@ID-203936.news.uni-berlin.de:

[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.
--
http://www.victim-prime.dsl.pipex.com/
Jul 19 '05 #24
On Mon, 20 Oct 2003 04:15:23 GMT, Alf P. Steinbach <al***@start.no> wrote:
On Mon, 20 Oct 2003 04:03:09 GMT, gr**********@pacbell.net wrote:

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?


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.
--
grzegorz
Jul 19 '05 #25
On Mon, 20 Oct 2003 11:25:12 GMT, gr**********@pacbell.net wrote:
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?
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?

--
Be seeing you.
Jul 19 '05 #26
On Mon, 20 Oct 2003 10:12:22 +0200, Karl Heinz Buchegger
<kb******@gascad.at> wrote:


gr**********@pacbell.net wrote:

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.


Yes, but the code doesn't neccesery have to use dynamic allocation.
--
grzegorz
Jul 19 '05 #27
On Sun, 19 Oct 2003 21:40:55 +0100, "Jamie Burns" <se*****@email.com>
wrote:
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
Jul 19 '05 #28
On Mon, 20 Oct 2003 11:42:06 GMT, gr**********@pacbell.net wrote:
On Mon, 20 Oct 2003 10:12:22 +0200, Karl Heinz Buchegger
<kb******@gascad.at> wrote:


gr**********@pacbell.net wrote:

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.


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


Often it does (e.g. polymorphism or non-copyable objects).

Tom
Jul 19 '05 #29


gr**********@pacbell.net wrote:

On Mon, 20 Oct 2003 10:12:22 +0200, Karl Heinz Buchegger
<kb******@gascad.at> wrote:


gr**********@pacbell.net wrote:

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.


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++.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 19 '05 #30
gr**********@pacbell.net wrote:
On Mon, 20 Oct 2003 01:32:05 +0100, lilburne <li******@godzilla.net> wrote:
gr**********@pacbell.net wrote:

You can get away with the reference if you know where the data is
going to end up, but say for example that calculate_some_geometry() is
destructive and may fail, you'll want to do the calculation and only
if it is OK replace the original data. Taking over a pointer avoids a
final copy.


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.

Jul 19 '05 #31
Rob Williscroft wrote:
lilburne wrote in news:bm************@ID-203936.news.uni-berlin.de:

[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.

Jul 19 '05 #32
lilburne wrote in news:bn************@ID-203936.news.uni-berlin.de:
Rob Williscroft wrote:
lilburne wrote in news:bm************@ID-203936.news.uni-berlin.de:

[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.
--
http://www.victim-prime.dsl.pipex.com/
Jul 19 '05 #33
Rob Williscroft wrote:
lilburne wrote in news:bn************@ID-203936.news.uni-berlin.de:

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.


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.

Jul 19 '05 #34
lilburne wrote in news:bn************@ID-203936.news.uni-berlin.de:

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.
--
http://www.victim-prime.dsl.pipex.com/
Jul 19 '05 #35
gr**********@pacbell.net wrote in message news:<op**************@news.sf.sbcglobal.net>...
On Mon, 20 Oct 2003 04:15:23 GMT, Alf P. Steinbach <al***@start.no> wrote:
On Mon, 20 Oct 2003 04:03:09 GMT, gr**********@pacbell.net wrote:

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?


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.
Jul 19 '05 #36
Rob Williscroft wrote:
lilburne wrote in news:bn************@ID-203936.news.uni-berlin.de:

Avoiding a default constructor by return value optimization


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.

Jul 19 '05 #37
lilburne wrote in news:bn************@ID-203936.news.uni-berlin.de:
Rob Williscroft wrote:
lilburne wrote in news:bn************@ID-203936.news.uni-berlin.de:

Avoiding a default constructor by return value optimization


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?


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.
--
http://www.victim-prime.dsl.pipex.com/
Jul 19 '05 #38
Rob Williscroft wrote:
lilburne wrote in news:bn************@ID-203936.news.uni-berlin.de:

Rob Williscroft wrote:

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?

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.
Jul 19 '05 #39
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.
Jul 19 '05 #40
lilburne wrote in news:bn************@ID-203936.news.uni-berlin.de:

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.


Unfortunatly I can't respond to that as you provided no code and
I don't currently have access to gcc 3.3.1.

#include <iostream>
#include <vector>

using namespace std;

struct test
{
test() { cerr << "Construct\n"; }
test(test const &) { cerr << "Copy\n"; }
~test() { cerr << "Destructor\n"; }

test &operator=(test const &) { cerr << "Assign\n"; return *this; }
};

vector< test > nrv_test()
{
vector< test > nrv;
nrv.push_back( test() );
cerr << "Return\n";
return nrv;
}

int main()
{
vector< test > a = nrv_test() ;
cerr << "Returned\n";
}

I get:

$ g++ -ansi -pedantic test.cpp -o 1.exe

$ 1
Construct
Copy
Destructor
Return
Returned
Destructor

$ g++ --version
g++.exe (GCC) 3.2.3 (mingw special 20030504-1)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 19 '05 #41
Julián Albo wrote:

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.


#include <iostream>
#include <vector>

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

class Point {
public:
Point();
Point(const Point& p);
Point& operator=(const Point& p);
~Point();
};

Point::Point()
{
cout << "Point construction" << endl;
}
Point::Point(const Point& p)
{
cout << "Point copy construction" << endl;
}
Point::~Point()
{
cout << "Point destructor" << endl;
}

Point& Point::operator=(const Point& p)
{
cout << "Point assignment --- XXXX" << endl;
}

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

void f(std::vector< Point > & vec) {
}

int main()
{
cout << "Create start" << endl;
std::vector< Point > res( create() );
cout << "Create finished" << endl;
f(res);
cout << "Create start" << endl;
res = create();
cout << "Create finished" << endl;
f(res);
return 0;
}

Output is:
Create start
Point construction
Point copy construction
Point copy construction
Point copy construction
Point destructor
Point destructor
Create finished
Create start
Point construction
Point copy construction
Point copy construction
Point copy construction
Point destructor
Point destructor
Point assignment --- XXXX
Point assignment --- XXXX
Point destructor
Point destructor
Create finished
Point destructor
Point destructor

As you can see the second call to create() results in the
copying (assignment). The NVRO optimization is minimal and I
can get the same effect as an earlier contributor said by
using the idiom:

vector < Point > vec;
create(vector< Point >& vec);

which isn't compiler dependent.

Jul 19 '05 #42
On Tue, 21 Oct 2003 21:23:51 +0100, lilburne <li******@godzilla.net> wrote:
Julián Albo wrote:

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.


#include <iostream>
#include <vector>

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

class Point {
public:
Point();
Point(const Point& p);
Point& operator=(const Point& p);
~Point();
};

Point::Point()
{
cout << "Point construction" << endl;
}
Point::Point(const Point& p)
{
cout << "Point copy construction" << endl;
}
Point::~Point()
{
cout << "Point destructor" << endl;
}

Point& Point::operator=(const Point& p)
{
cout << "Point assignment --- XXXX" << endl;
}

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

void f(std::vector< Point > & vec) {
}

int main()
{
cout << "Create start" << endl;
std::vector< Point > res( create() );
cout << "Create finished" << endl;
f(res);
cout << "Create start" << endl;
res = create();
cout << "Create finished" << endl;
f(res);
return 0;
}

Output is:
Create start
Point construction
Point copy construction
Point copy construction
Point copy construction
Point destructor
Point destructor
Create finished
Create start
Point construction
Point copy construction
Point copy construction
Point copy construction
Point destructor
Point destructor
Point assignment --- XXXX
Point assignment --- XXXX
Point destructor
Point destructor
Create finished
Point destructor
Point destructor

As you can see the second call to create() results in the
copying (assignment). The NVRO optimization is minimal and I
can get the same effect as an earlier contributor said by
using the idiom:

vector < Point > vec;
create(vector< Point >& vec);

which isn't compiler dependent.


None of you have tested NRVO (Named Return Value Optimization), which,
incidentally, you don't even spell correctly... ;-)

RVO and NRVO are two different things.

In the case of NRVO there is a _named_ return value, which is a
language extension, not part of standard C++.

And just for the record, neither RVO nor NRVO have any bearing on usage
or not of std::auto_ptr.

Hth.

Jul 19 '05 #43
lilburne escribió:
As you can see the second call to create() results in the
copying (assignment). The NVRO optimization is minimal and I


The second call is an assignment, not an initialization. Initializtion
is not subject of that optimization.

Regards.
Jul 19 '05 #44
Julián Albo wrote:
lilburne escribió:

As you can see the second call to create() results in the
copying (assignment). The NVRO optimization is minimal and I

The second call is an assignment, not an initialization. Initializtion
is not subject of that optimization.


That was the whole point of why someone would use a pointer
rather than an object, which could involve the copying of a
whole mess of data. Some one suggested NVRO was a solution,
it clearly is not.

Jul 19 '05 #45
Alf P. Steinbach wrote:
RVO and NRVO are two different things.

In the case of NRVO there is a _named_ return value, which is a
language extension, not part of standard C++.

And just for the record, neither RVO nor NRVO have any bearing on usage
or not of std::auto_ptr.


That's what I said. But sometimes its worth humouring
someone for awhile.
Jul 19 '05 #46

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

Similar topics

1
by: Jason Heyes | last post by:
My main program #include <iostream> #include <algorithm> #include <iterator> #include <vector> #include "M.h" using namespace std; int main()
5
by: gg | last post by:
I am getting the following compilation errors with the following program. My compiler is aCC 03.27 on HP-UX11 - #include <iostream> using namespace std; #include <list> #include <memory>...
4
by: Rein Anders Apeland | last post by:
Consider the following working code: #include <memory> #include <iostream> void print_ptr( const std::auto_ptr< int > & thePtr = std::auto_ptr< int >() ) {
14
by: Andrew | last post by:
Hello all: After spending some time figuring out auto_ptr class' implementation, I decided to write a small article detailing its use of the auto_ptr_ref proxy class to enable construction and...
9
by: dragoncoder | last post by:
Hi all, I am trying to understand the auto_ptr_ref role in the implementation of auto_ptr<>. I read the information on net but still not 100% sure of it. My plan is as follows. 1. To see the...
14
by: Pep | last post by:
I have a method in a class like this class myClass { ... ctros, dtor, etc ... string myClassMethod() { string myString = "";
39
by: Andre Siqueira | last post by:
Hello all, I have a member function like thist: Query(const std::string & id, std::auto_ptr<Modifiermodif = std::auto_ptr<Modifier>()) when a try to instantiate a Query like ...
10
by: mosfet | last post by:
Hi, Let's say I have a vector of auto_ptr defined like this : vector< auto_ptr<T v; is it allowed ? Is there any side effects ? If it's not a good idea, how can I fix this ?
17
by: Ankur Arora | last post by:
Hi All, I'm building a sample application that uses a custom auto_ptr implementation. The program crashes with the following output:- Output (Debug Assertion failed) ----------
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
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...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.