I've posted a question as a follow-up to this answer, see stackoverflow.com/questions/704780/class... Assming your class does not have a user-defined copy constructor, then no, it is probably (see below) not safe. When your class is copied (as will happen when it is added to a vector) the copy constructor of the auto_ptr will be used. This has the weird behaviour of tranferring ownership of the thing being copied to the copy and, so the thing being copied's pointer is now null It is possible, though unlikely, that you actually want this behaviour, in which case an auto_ptr is safe.
Assuming you do not, you should either: add a copy constructor to manage the copying Note this is not enough - see the follow-up question mentioned above for more info or: use a smarter, possibly reference counted pointer, such as one of the boost smart pointers.
I've posted a question as a follow-up to this answer, see stackoverflow.com/questions/704780/class.... Assming your class does not have a user-defined copy constructor, then no, it is probably (see below) not safe. When your class is copied (as will happen when it is added to a vector) the copy constructor of the auto_ptr will be used.
This has the weird behaviour of tranferring ownership of the thing being copied to the copy and, so the thing being copied's pointer is now null. It is possible, though unlikely, that you actually want this behaviour, in which case an auto_ptr is safe. Assuming you do not, you should either: add a copy constructor to manage the copying Note this is not enough - see the follow-up question mentioned above for more info.
Or: use a smarter, possibly reference counted pointer, such as one of the boost smart pointers.
In the example in the question, I feel it is worth pointing out that there is a copy constructor generated by the compiler. – 1800 INFORMATION Mar 31 '09 at 8:56 modified answer to cover this – anon Mar 31 '09 at 8:58 You actually do NOT want the implicit behavior, as it violates a basic STL assumption on your type: All copies of an object are equal. E.g.
Std::sort WILL break your vector, if copying a MyClass to use as a pivot strips the source object in the vector from its MyOtherClass . – MSalters Mar 31 '09 at 14:53 yeah if you rely on that implicit behavior, you have undefined behavior. Your type T has to be copy constructible.
Can't work with auto_ptr as a member. – Johannes Schaub - litb Mar 31 '09 at 15:24 @MSalters - maybe he doesn't want to sort the vector? – anon Mar 31 '09 at 15:34.
It is not safe, bacause when container will copy MyClass instnace default copy operator will call copy for all members - and for auto_ptr member too and we will have same situation as you describe in your question ( storing auto_ptr in container ) BTW: for avoid confusion at compile time add private: MyClass& operator=( const MyClass& ); MyClass( const MyClass& ); compiler output error if you will try use copy operators, this can save you from hours of debug.
A good idea in general, but in this case he won't be able to add to a vector if he makes the copy ctor & op= private. – anon Mar 31 '09 at 8:57 ANd that's exactly why it's a good idea in this case. It turns a possible runtime error (null pointer dereference) into a compile-time error (MyClass can't be copied) – MSalters Mar 31 '09 at 14:55.
As Neil Butterworth said, auto_ptr is probably not the way to go. Boost::shared_ptr clearly is, but you say you can't use boost. Let me mention that you could download boost, extract what you need for shared\ptr only using the bcp tool and use boost::shared_ptr.
It would only mean a few added hpp files in your project. I believe it's the right way to go.
Benoit, I'm on GCC 4.1.2, didn't know shared_ptr is available in tr1. Someone gave a hint; the comment is lost after StackOverflow's maintenance. I'm now using std::tr1::shared_ptr.
– artknish Mar 31 '09 at 12:49.
It is not valid to have an object that contains an auto_ptr in a standard container. You run into undefined behavior. Two common problems: std::vector::resize copies its argument into each created element.
The first copy will "succeed" (see below why not), but each further copy will be empty, because the element copied is also empty! If something during reallocation throws, you can happen to have some elements copied (to a new buffer) - but the copy being thrown away - and other elements not, because push_back must not have any effects if an exception is being thrown. Thus some of your elements are now empty.As this is all about undefined behavior it does not really matter.
But even if we try to come up with this behavior based on what we think is valid, we would fail anyway. All the member functions like push_back, resize and so on have a const reference that takes an object of type T. Thus, a reference of type T const& is tried to copied into elements of the vector.
But the implicitly created copy constructor/copy assignment operator looks like T(T&) - that is, it requires a non-const object to be copied from! Good implementations of the Standard library check that, and fail to compile if necessary. Until the next C++ version, you have to live with this.
The next one will support element types that are merely movable. That is, a moved object does not need to be equal to the object moved to. That will allow putting streams, transfer-of-ownership pointers and threads into containers.
See what the Standard says for this (17.4.3.6): In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ Standard Library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.In particular, the effects are undefined in the following cases: for types used as template arguments when instantiating a template component, if the operations on the type do not implement the semantics of the applicable Requirements subclause (20.1.5, 23.1, 24.1, 26.1).
Sorry - you still have not demonstrated UB. Please post some actual C++ CODE (not hand-waving) that does so. I have the utmost respect for your opinions, but I really do think that you are wrong here.
– anon Mar 31 '09 at 20:33 the very nature of UB is that it can't be demonstrated :) – Johannes Schaub - litb Mar 31 '09 at 20:48 Not so! Char * p = 0; *p = 'x'; // undefined behaviour – anon Mar 31 '09 at 20:53 I thought you already know how to do it. Struct f { auto_ptr p; }; vector q; // undefined behavior – Johannes Schaub - litb Mar 31 '09 at 20:58 i'll leave this issue as it is now, because you already know everything to know about it ;) see you again on usenet – Johannes Schaub - litb Mar 31 '09 at 21:00.
Copying MyClass object will cause either call to assignment operator or copy constructor. If they are not overloaded to handle auto_ptr in unusual way, they will propagate the call to copy constructor (or assignment operator) to the auto_ptr member. This may lead to problems described in question you had linked.
The reason why it is not safe to instanciate a vector of auto_pointer is that there is an algorithm : sort(), that will do a copy of one object in your container on the stack. (sort() implements quicksort which needs a "pivot") And therefore deleting it when going out of scpope of the sort() function. As well any algorithm, or function of your own that are able to take your container as parameter, and copy one of its object on the stack will cause this issue as a result.
Well in your case, it is simple you must ensure your class does not behaves as an auto_ptr, or ensure you will never call such function/algorithm that can delete your underlying objects. The first solution is best, according to me :) So your copy constructor and your affectation operator as well, should not give away property of the pointer object. The best way to achieve that is to wrapp a boost smart pointer instead of an auto_ptr, to make your container safe when calling such function/algorithm.By the way according to me, defining a better copy constructor/affectation operator to bypass this issue is not a good solution: I can't see a good copy constructor implementation (and affectation operator as well) that could keep safe the result of applying the sort() algorithm.
If you want to use a class that uses auto_ptr in a container, you can just provide a copy-constructor and assignment operator yourself: class MyClass { private: const std::auto_ptr obj; // Note const here to keep the pointer from being modified. Public: MyClass(const MyClass &other) : obj(new MyOtherClass(*other. Obj)) {} MyClass &operator=(const MyClass &other) { *obj = *other.
Obj; return *this; } }; But as mentioned elsewhere, the standard lets containers make copies and assignments and assumes that the contained classes will behave in a specific manner that auto_ptr violates. By defining the methods above, you can make a class that contains an auto_ptr behave. Even if your implementation works fine with auto_ptrs, you run the risk of finding another implementation doesn't work.
The standard only make guarantees of performance and observable behaviour, not implementation.
It will not work. Auto_ptr doesn't count references which means at the first destructor call your pointer will be freed. Use boost::shared_ptr instead.
All the member functions like push_back, resize and so on have a const reference that takes an object of type T. Thus, a reference of type T const& is tried to copied into elements of the vector. But the implicitly created copy constructor/copy assignment operator looks like T(T&) - that is, it requires a non-const object to be copied from!
Good implementations of the Standard library check that, and fail to compile if necessary.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.