auto_ptr

P

puzzlecracker

I am using pointers in my program and they obviously make me a bit
nervious about possible program states. I am giving serious thoughs
about using auto_ptr but unsure whether they can be placed in vectors.

This is approximaton of where I need to use them

/currently
class A {
//some members
virtual ~A();
};

class B:public A {

//some members

};


class C {

public:
std::vector<A*> vec;

~c(){// I do the clean up here}
};



....

I am considering the revision to
include<memory>

class C {

public:
std::vector<auto_ptr<A*> > vec;

};
During the execution I remove as well as add as well as modify the
content of the vector. Does anyone think whether it might conflict with
ownership issues in the auto_ptr<A*>;



----

another problem, this time unrelated to auto_ptr. I maintain a vecotr
of pointers where copies of some of this pointers are being kept
outside. Ex.

class A {

};

class B{
A * const a; // pay attention: I cannot modify the content of a
// B has a copy of *a which is stored in the vector C
};


class C {

vector<A *> vec;
};


Only issues I currenly forsee is that copy of a pointer in B can be
invalidated if destroyed in vec, but can it become invalidate by some
other vector operations?



would this scheme work if I were to use auto_ptr instead?

unfortunately, I cannot use boost lib for my production code (so, there
is not shared_ptr or valjue_ptr available to me).


Thank
 
A

Axter

puzzlecracker said:
I am using pointers in my program and they obviously make me a bit
nervious about possible program states. I am giving serious thoughs
about using auto_ptr but unsure whether they can be placed in vectors.

This is approximaton of where I need to use them

/currently
class A {
//some members
virtual ~A();
};

class B:public A {

//some members

};


class C {

public:
std::vector<A*> vec;

~c(){// I do the clean up here}
};



...

I am considering the revision to
include<memory>

class C {

public:
std::vector<auto_ptr<A*> > vec;

};
During the execution I remove as well as add as well as modify the
content of the vector. Does anyone think whether it might conflict with
ownership issues in the auto_ptr<A*>;



----

another problem, this time unrelated to auto_ptr. I maintain a vecotr
of pointers where copies of some of this pointers are being kept
outside. Ex.

class A {

};

class B{
A * const a; // pay attention: I cannot modify the content of a
// B has a copy of *a which is stored in the vector C
};


class C {

vector<A *> vec;
};


Only issues I currenly forsee is that copy of a pointer in B can be
invalidated if destroyed in vec, but can it become invalidate by some
other vector operations?



would this scheme work if I were to use auto_ptr instead?

unfortunately, I cannot use boost lib for my production code (so, there
is not shared_ptr or valjue_ptr available to me).


Thank
You can not use an auto_ptr in a vector. In a compliant C++ compiler,
an auto_ptr will not even compile in a vector.
For your requirement I recommend you use a clone pointer or a cow (Copy
on Write) smart pointer.
You can use one of the following classes:
copy_ptr
http://code.axter.com/copy_ptr.h

cow_ptr
http://code.axter.com/cow_ptr.h

I recommend using the cow_ptr over the clone pointer, becuase it's more
efficinet.
Can be use like this:
vector<cow_ptr<A> > vA;

For more information on clone pointers, see following link:
http://www.codeguru.com/Cpp/Cpp/algorithms/general/article.php/c10407/
 
M

mlimber

Axter said:
puzzlecracker wrote: [snip]
unfortunately, I cannot use boost lib for my production code (so, there
is not shared_ptr or valjue_ptr available to me).

You can not use an auto_ptr in a vector. In a compliant C++ compiler,
an auto_ptr will not even compile in a vector.
For your requirement I recommend you use a clone pointer or a cow (Copy
on Write) smart pointer.
You can use one of the following classes:
copy_ptr
http://code.axter.com/copy_ptr.h

cow_ptr
http://code.axter.com/cow_ptr.h

I recommend using the cow_ptr over the clone pointer, becuase it's more
efficinet.
Can be use like this:
vector<cow_ptr<A> > vA;

For more information on clone pointers, see following link:
http://www.codeguru.com/Cpp/Cpp/algorithms/general/article.php/c10407/

If the OP is willing to use a third-party pointer class, s/he should
obviously prefer Boost's because (1) it is part of TR1 and likely will
be part of the standard soon, (2) more programmers are (and will be!)
familiar with it, and (3) it has been thoroughly tested and
peer-reviewed. Just as s/he would do with your copy_ptr or cow_ptr, the
OP might just lift that one part of Boost and plop it into his/her
project directly without installing all of Boost. I wonder why the OP
"cannot" use it.

Cheers! --M
 
K

Kai-Uwe Bux

mlimber said:
Axter said:
puzzlecracker wrote: [snip]
unfortunately, I cannot use boost lib for my production code (so, there
is not shared_ptr or valjue_ptr available to me).

You can not use an auto_ptr in a vector. In a compliant C++ compiler,
an auto_ptr will not even compile in a vector.
For your requirement I recommend you use a clone pointer or a cow (Copy
on Write) smart pointer.
You can use one of the following classes:
copy_ptr
http://code.axter.com/copy_ptr.h

cow_ptr
http://code.axter.com/cow_ptr.h

I recommend using the cow_ptr over the clone pointer, becuase it's more
efficinet.
Can be use like this:
vector<cow_ptr<A> > vA;

For more information on clone pointers, see following link:
http://www.codeguru.com/Cpp/Cpp/algorithms/general/article.php/c10407/

If the OP is willing to use a third-party pointer class, s/he should
obviously prefer Boost's because (1) it is part of TR1 and likely will
be part of the standard soon, (2) more programmers are (and will be!)
familiar with it, and (3) it has been thoroughly tested and
peer-reviewed. Just as s/he would do with your copy_ptr or cow_ptr, the
OP might just lift that one part of Boost and plop it into his/her
project directly without installing all of Boost. I wonder why the OP
"cannot" use it.

Actually, which smart pointer to use should foremost depend on the semantics
that you need. As I understand, cow_ptr and copy_ptr provide copy-semantics
for pointees whereas boost provides reference counted garbage collecting
pointers with reference semantics. One is not a substitute for the other.


Best

Kai-Uwe Bux
 
A

Axter

mlimber said:
Axter said:
puzzlecracker wrote: [snip]
unfortunately, I cannot use boost lib for my production code (so, there
is not shared_ptr or valjue_ptr available to me).

You can not use an auto_ptr in a vector. In a compliant C++ compiler,
an auto_ptr will not even compile in a vector.
For your requirement I recommend you use a clone pointer or a cow (Copy
on Write) smart pointer.
You can use one of the following classes:
copy_ptr
http://code.axter.com/copy_ptr.h

cow_ptr
http://code.axter.com/cow_ptr.h

I recommend using the cow_ptr over the clone pointer, becuase it's more
efficinet.
Can be use like this:
vector<cow_ptr<A> > vA;

For more information on clone pointers, see following link:
http://www.codeguru.com/Cpp/Cpp/algorithms/general/article.php/c10407/

If the OP is willing to use a third-party pointer class, s/he should
obviously prefer Boost's because (1) it is part of TR1 and likely will
be part of the standard soon, (2) more programmers are (and will be!)
familiar with it, and (3) it has been thoroughly tested and
peer-reviewed. Just as s/he would do with your copy_ptr or cow_ptr, the
OP might just lift that one part of Boost and plop it into his/her
project directly without installing all of Boost. I wonder why the OP
"cannot" use it.

Cheers! --M

These are good points, but the cow_ptr and copy_ptr gives the OP
functionality that the boost::shared_ptr does not. (See CodeGuru Link)
Moreover, the clone_ptr has been peer reviewed before being posted at
CodeGuru.
The code for both the copy_ptr and the cow_ptr are based on the
clone_ptr class.

I've previously tried pulling code from the boost library, and I found
that either I had to make changes to the original code, or I had to
pull in a lot of associated headers with the class I desired.
One of my major critiques over the boost library is that it is not
design to be encapsulated. I do fully understand their logic behind
this, and it's valid.
But this still makes it hard to pull classes as standalone from the
boost library.

If the OP wants something simple, easy to use, and (IMHO) more
functional for abstract pointers, then I recommend the OP use the
cow_ptr or copy_ptr smart class over the boost::shared_ptr.
 
M

mlimber

Kai-Uwe Bux said:
Actually, which smart pointer to use should foremost depend on the semantics
that you need. As I understand, cow_ptr and copy_ptr provide copy-semantics
for pointees whereas boost provides reference counted garbage collecting
pointers with reference semantics. One is not a substitute for the other.

Of course you are right. However, I would suggest that using a standard
(or in this case, soon-to-be-standard) component for one and only one
of its properties is sometimes preferable to borrowing a less
rigorously tested component or to hand-rolling a potentially tricky
piece of code to get lesser but otherwise equivalent functionality,
even if doing so comes with a bit of unneeded overhead.

Cheers! --M
 
A

Axter

mlimber said:
Of course you are right. However, I would suggest that using a standard
(or in this case, soon-to-be-standard) component for one and only one
of its properties is sometimes preferable to borrowing a less
rigorously tested component or to hand-rolling a potentially tricky
piece of code to get lesser but otherwise equivalent functionality,
even if doing so comes with a bit of unneeded overhead.

Cheers! --M

The new C++ standard, will not be out any time soon. So you should not
rely on this, and by the time it does come out, a lot could have
changed.
Moreover, when I'm ready, I do plan on proposing that the cow_ptr and
copy_ptr be added to the boost library.
So for all you know, these pointers could someday be added to the
standard as well.
If you think boost::shared_ptr gives you equivalent functionality to a
cow_ptr, then you don't understand the functionality of one or more of
these two smart pointers.
Please read the link, before making a judgement call. I don't
recommend giving advise when you don't have complete information.
 
K

Kai-Uwe Bux

mlimber said:
Of course you are right. However, I would suggest that using a standard
(or in this case, soon-to-be-standard) component for one and only one
of its properties is sometimes preferable to borrowing a less
rigorously tested component or to hand-rolling a potentially tricky
piece of code to get lesser but otherwise equivalent functionality,
even if doing so comes with a bit of unneeded overhead.

I agree, at least in general. However, I just fail to see how these to
gadgets provide "lesser but otherwise equivalent functionality". These
smart pointers are just different. The fact that both overload operator*
does not means that they are even similar.

One of them (boost) is a real pointer substitute that tries hard to preserve
as much of pointer like behavior while freeing the client from memory
management. The copy-pointer on the other hand is a pointer only by lack of
language support: it really wants to be a smart reference that has the look
and feel of a variable except that it can be used polymorphically. Since
C++ does not allow for overloading the dot-operator, you have to use
pointer syntax.

The following code shows the difference, and it is not a minor one.


#include <iostream>

/*
A simple copy pointer implementation
*/

// The clone_traits function:
template < typename T, typename D >
T * clone ( T * ptr ) {
return( new D ( *( dynamic_cast<D*>( ptr ) ) ) );
}

template < typename T >
T * simple_clone ( T * ptr ) {
return( new T ( *ptr ) );
}


// forward declarations:
template < typename T >
class copy_ptr;

template < typename T >
void swap ( copy_ptr< T > &, copy_ptr< T > & );


// implementation:
template < typename T >
class copy_ptr {

friend void swap<> ( copy_ptr<T> &, copy_ptr<T> & );

/*
The idea is that in addition to a pointer, we also need
a pointer to the appropriate clone_traits function.
*/
T * raw_ptr;
T * ( *clone_fct ) ( T * );

public:

copy_ptr ( void )
: raw_ptr ( new T )
, clone_fct( simple_clone<T> )
{}

copy_ptr ( T * ptr )
: raw_ptr ( ptr )
, clone_fct ( simple_clone<T> )
{}

template < typename D >
copy_ptr ( D * ptr )
: raw_ptr ( ptr )
, clone_fct ( clone<T,D> )
{}

// copy construction clone_traits:
copy_ptr ( copy_ptr const & other )
: raw_ptr ( other.clone_fct( other.raw_ptr ) )
, clone_fct ( other.clone_fct )
{}

// destruction frees the pointee
~copy_ptr ( void ) {
delete( raw_ptr );
}

// assignment reduces to copy construction:
copy_ptr & operator= ( copy_ptr const & other ) {
copy_ptr dummy ( other );
swap( *this, dummy );
return( *this );
}

T const * operator-> ( void ) const {
return( raw_ptr );
}

T * operator-> ( void ) {
return( raw_ptr );
}

T const & operator* ( void ) const {
return( *raw_ptr );
}

T & operator* ( void ) {
return( *raw_ptr );
}

}; // copy_ptr<T>

template < typename T >
void swap ( copy_ptr< T > & p, copy_ptr< T > & q ) {
std::swap( p.raw_ptr, q.raw_ptr );
std::swap( p.clone_fct, p.clone_fct );
}


#include <boost/shared_ptr.hpp>

template < template <class> class SmartPtr >
void print_test ( void ) {
SmartPtr<int> i_ptr ( new int ( 5 ) );
SmartPtr< int > j_ptr;
j_ptr = i_ptr;
*j_ptr = 6;
std::cout << *i_ptr << " vs. " << *j_ptr << '\n';
}

int main ( void ) {
print_test< boost::shared_ptr >();
print_test< copy_ptr >();
}

output:

news_group> a.out
6 vs. 6
5 vs. 6


Best

Kai-Uwe Bux
 
M

mlimber

Kai-Uwe Bux said:
I agree, at least in general. However, I just fail to see how these to
gadgets provide "lesser but otherwise equivalent functionality". These
smart pointers are just different.
[snip]

You and Axter are right. I didn't look closely enough at the referenced
code, and I was imprecise in communicating above. To give it another
go... ISTM that the OP just wants a smart pointer that cleans up after
itself (cf. the attempted use of std::auto_ptr) but with the necessary
copy semantics for standard containers. In that limited sense, both
boost::shared_ptr and Axter's copy_ptr are equivalent and would fit the
bill, and their actual differences may be practically irrelevant to the
OP's actual application. Thus my suggestion about (semi-)standard
components may apply. (On the other hand, the smart pointers'
differences may be relevant if the OP needs to deal with the
polymorphic objects or clone-type copying. If that is the case,
however, it was not apparent to me from the original post.)

Sorry for the confusion!

Cheers! --M
 
M

mlimber

Axter said:
The new C++ standard, will not be out any time soon. So you should not
rely on this, and by the time it does come out, a lot could have
changed.
Moreover, when I'm ready, I do plan on proposing that the cow_ptr and
copy_ptr be added to the boost library.
So for all you know, these pointers could someday be added to the
standard as well.
[snip]

Fair enough, but boost::shared_ptr has already made it into TR1, which
is intended "to build more widespread existing practice for an expanded
C++ standard library." The components therein may not ever be
standardized, but pragmatically speaking, they have higher probability
of inclusion than components not mentioned.

Cheers! --M
 
R

Ron Natalie

You can not use an auto_ptr in a vector. In a compliant C++ compiler,
an auto_ptr will not even compile in a vector.

There's no requirement that the compiler detect this.
You're on your own to assure your objects meet the container
requirements.
 
A

Axter

Ron said:
There's no requirement that the compiler detect this.
You're on your own to assure your objects meet the container
requirements.

In Item#8 of Scott Meyers's Effective STL book, he states the
following:
*****************************************************************
Containers Of auto_ptr (COAPs) are prohibited. Code attempting to use
them shouldn't compile. The C++ Standardization Committe expended
untold effort to arrange for that to be the case. I shouldn't have to
say anything about COAPs, because your compiler should have plenty to
say about such containers, and all of it should be uncomplementary.

Alas, many programmers use STL platforms that fail to reject COAPs.
*****************************************************************
 
R

Ron Natalie

Axter said:
In Item#8 of Scott Meyers's Effective STL book, he states the
following:
*****************************************************************
Containers Of auto_ptr (COAPs) are prohibited. Code attempting to use
them shouldn't compile. The C++ Standardization Committe expended
untold effort to arrange for that to be the case. I shouldn't have to
say anything about COAPs, because your compiler should have plenty to
say about such containers, and all of it should be uncomplementary.

Alas, many programmers use STL platforms that fail to reject COAPs.
*****************************************************************
Scott is expressing an opinion here. It's not clear from the way
he worded it, but the STANDARD does not put any requirement on the
compiler to catch that. Yes, generally you get ancillary errors
from inside the container code because of some downstream syntax
error, but as soon as you put a non-copyconstructable/non-assignable
object into a container, you have undefined behavior. There's even
a note in the standard that reiterates that principle:

Note: The uses of auto_ptr include providing temporary
exception-safety for dynamically allocated memory, passing
ownership of dynamically allocated memory to a function,
and returning dynamically allocated memory from a function.
auto_ptr does not meet the CopyConstructible and Assignable
requirements for Standard Library container elements and thus
instantiating a Standard Library container with an auto_ptr
results in undefined behavior. —end note.

The standard doesn't require, nor is there any good way for an
implementation to tell if the container requiements are met.
You can have the copy-constructor and the assignment operator
defined without them doing the right thing to meet the container
requirements.
 
B

Brian Cain

Kai-Uwe Bux wrote:
....
Actually, which smart pointer to use should foremost depend on the semantics
that you need. As I understand, cow_ptr and copy_ptr provide copy-semantics
for pointees whereas boost provides reference counted garbage collecting
pointers with reference semantics. One is not a substitute for the other.

Which smart pointer best simulates the existing language features of
Perl/Python/Java/etc?

-Brian
 
K

Kai-Uwe Bux

Brian said:
Kai-Uwe Bux wrote:
...

Which smart pointer best simulates the existing language features of
Perl/Python/Java/etc?

Your question does not have a useful answer since is too vague.

a) Which "existing language features" are you refering to?
b) What is the design problem you are trying to solve using smart pointers?


Best

Kai-Uwe Bux
 
A

Axter

Ron said:
Scott is expressing an opinion here. It's not clear from the way
he worded it, but the STANDARD does not put any requirement on the
compiler to catch that. Yes, generally you get ancillary errors
from inside the container code because of some downstream syntax
error, but as soon as you put a non-copyconstructable/non-assignable
object into a container, you have undefined behavior. There's even
a note in the standard that reiterates that principle:

Note: The uses of auto_ptr include providing temporary
exception-safety for dynamically allocated memory, passing
ownership of dynamically allocated memory to a function,
and returning dynamically allocated memory from a function.
auto_ptr does not meet the CopyConstructible and Assignable
requirements for Standard Library container elements and thus
instantiating a Standard Library container with an auto_ptr
results in undefined behavior. -end note.

The standard doesn't require, nor is there any good way for an
implementation to tell if the container requiements are met.
You can have the copy-constructor and the assignment operator
defined without them doing the right thing to meet the container
requirements.

Actually, what the standard is specifically stating above, is that
instantiating a vector of auto_ptr results in undefined behavior.
So,...
vector<auto_ptr<int>> vInt;
So above line of code would result in undefined behavior, which means
some compilers could generate a compile error, and some will not.
****However****
Calling the above type push_back will not result in undefeind behavior,
and IAW C++ standard will generate a compile error.
vector<auto_ptr<int>> vInt; //Undefined behavior
vInt.push_back(new int); //Will result in compile error
IAW C++ standards, calling the push_back method will result in a
compile error.
In fact, IAW C++ standard, calling any vector member method that will
put a auto_ptr into the vector will generate a compile time error.
vInt.resize(123); //Will result in compile error IAW C++ standard
vInt.assign(123, new int); //Will result in compile error IAW C++
standard
vInt[0] = new int; //Will result in compile error IAW C++ standard

Declaring this type may result in undefined behavior, however, actually
trying to use it does result in defined behavior, which is to give a
compile time error.
For details as to why this should result in a compile time error IAW
C++ standards, see Tommaso Galleri's post in the following link:
http://groups.google.com/group/comp...a5427/51bee63000510212?hl=en#51bee63000510212

As you can see from above link, many programmers seem to have this
misconception that using an STL container of auto_ptr does not result
in a compile time error IAW C++ standard.
 
R

Ron Natalie

Axter said:
Calling the above type push_back will not result in undefeind behavior,
and IAW C++ standard will generate a compile error.

HUH? If the definition of such a structure is undefined behavior,
there is no bounds to what happens after that. The compiler is not
required to compile it or detect not compiling it. The standard
says if you have ANY undefined behavior, anything goes.
As you can see from above link, many programmers seem to have this
misconception that using an STL container of auto_ptr does not result
in a compile time error IAW C++ standard.

There is NO SUCH HREQUIREMENT. If there is undefined behavior, the
standard specifically says that there are no limits on the behavior.
This means that any other requirements of the standard CEASE TO APPLY.
 
A

Axter

Ron said:
HUH? If the definition of such a structure is undefined behavior,
there is no bounds to what happens after that. The compiler is not
required to compile it or detect not compiling it. The standard
says if you have ANY undefined behavior, anything goes.


There is NO SUCH HREQUIREMENT. If there is undefined behavior, the
standard specifically says that there are no limits on the behavior.
This means that any other requirements of the standard CEASE TO APPLY.

That standard is only stating that instantiating such a type results in
undefined behavior.
vector<auto_ptr<int>> vInt;
So the above results in undefeind behavior.
The standard does not say that calling it's members results in
undefined behavior.

So the following results in defined behavior:
vInt.push_back(new int);
According to the standard, the defined behavior is to give a compile
time error.

You're putting more into the undefined behavior statement then what is
in there.
Please read the standard again.
 
A

Axter

Ron said:
HUH? If the definition of such a structure is undefined behavior,
there is no bounds to what happens after that. The compiler is not
required to compile it or detect not compiling it. The standard
says if you have ANY undefined behavior, anything goes.


There is NO SUCH HREQUIREMENT. If there is undefined behavior, the
standard specifically says that there are no limits on the behavior.
This means that any other requirements of the standard CEASE TO APPLY.

There is a defined requirement, and if you're still in doubt, let me
spell it out.
Section 23.2.4.3 of the C++ standard shows the following function type
for vector::push_back:
void push_back(const & x);

Section 20.4.5 of the C++ standard shows the following for the auto_ptr
copy constructor:
auto_ptr(auto_ptr&) throw();
template<class Y> auto_ptr(auto_ptr<Y>&) throw();

Both copy constructors take non constant types.

So if you have a vector and an auto_ptr class that is compliant with
the C++ standard, it will not compile when you call member function
push_back.

And therefore, according to the C++ standard, calling methods that add
an auto_ptr type to a container of auto_ptr, will result in a compile
time error.
 

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

Forum statistics

Threads
474,262
Messages
2,571,047
Members
48,769
Latest member
Clifft

Latest Threads

Top