views:

169

answers:

2
#include<iostream>
#include<memory>
#include<stdio>

using namespace std;

class YourClass
{
   int y;
public:
   YourClass(int x) {
      y= x;
   }
};
class MyClass
{
   auto_ptr<YourClass> p;
public:
   MyClass() //:p(new YourClass(10)) 
   {
      p= (auto_ptr<YourClass>)new YourClass(10);
   }
   MyClass( const MyClass &) : p(new YourClass(10)) {}
   void show() {
      //cout<<'\n'<<p; //Was not working hence commented
      printf("%p\n",p);
   }
};

int main() {
   MyClass a;
   a.show();
   MyClass b=a;
   cout<<'\n'<<"After copying";
   a.show();//If I remove copy constructor from class this becomes NULL(the value of auto_ptr becomes NULL but if class has copy constructor it remains same(unchanged)
   b.show();//expected bahavior with copy construcotr and withought copy constructor
}

Making the problem more specific: Currently the class has copy constructor so there is no problem with the value of auto_ptr printed by a.show()(when it is called second time). It remians the same as it was when it was initiazed). It remians unchanged. If I remove the copy contructor from the class MyClass , the value of auto_ptr printed by a.show()(when it is called second time) is NULL.

A: 

You shouldn't be casting your class to the autoptr. I know that for sure. I am not sure off the top of my head what syntax it wants but it should be something like p = new YourClass().

Charles Eli Cheese
Sandeep
The raw pointer constructor is `explicit`, so that the correct syntax is: `auto_ptr<T> p( new T() );` (call the constructor explicitly). Using the cast will actually perform a similar operation: the cast will create a temporary `auto_ptr` created with the raw pointer constructor, that temporary will then be used with the copy constructor of the named variable being created.
David Rodríguez - dribeas
+8  A: 

What's happening is due to the strange (but only justifiable if you think about it) semantics of assigning or copying an auto_ptr, e.g.

auto_ptr<T> a;
auto_ptr<T> b(new T());
a = b; 

... or ...

auto_ptr<T> b(new T());
auto_ptr<T> a(b);

These will set a to b as expected, but they will also set b to NULL (see http://www.cplusplus.com/reference/std/memory/auto_ptr/auto_ptr/).

If you don't define a copy constructor for MyClass, then the compiler will generate one for you and will do just something similar to the above when it copies the auto_ptr member. Hence the copied from class will have a NULL member after the copy constructor has been called.

Andy
@Andy: These will set a to b as expected, but they will also set b to NULL Is there any hidden objective of making b NULL. This seems to be strange as it is not in case of raw pointers.
Sandeep
As you probably know, the point of auto_ptr is that when it goes out of scope, the object is destroyed and the memory used is freed. If two auto_ptrs point to the same object (as would be the case if b were not set to NULL) then when should the memory be freed--when a goes out of scope, or when b goes out of scope? If your answer is 'when both have gone out of scope', then consider using boost shared_ptr instead of auto_ptr.
Andy
dribeas -- thanks, changed.
Andy
@Andy : please check if it auto_ptr<T> b = new T(); works. I think it should be auto_ptr<T> b (new T()); or else you would require cast. auto_ptr<T> b = (auto_ptr<T>) new T()
Sandeep
@Sandeep: The problem there is resource management. When the auto pointer goes out of scope it will call delete in the internal pointer, if both auto pointers kept the pointer, then there would be a double delete. The design decision in `auto_ptr` was that assignment would transfer ownership, which seemed appropriate at the moment, but has proven not to be ideal. In the upcoming standard that single smart pointer will be replaced by three different versions `shared_ptr` (for reference counted shared ownership), ...
David Rodríguez - dribeas
..., `unique_ptr` (strict ownership, but the ability to release the resource so that code can manually take it away), and `scoped_ptr` (strict ownership that cannot be released). The use cases for the last two versions differ in that the `scoped_ptr` is limited to only working within a scope (thus the name) and the resource is guaranteed never to leave that scope. With the `unique_ptr` the user can handle the resource out of the scope through 'move semantics' (constructor or assignment) or explicit `release()` call.
David Rodríguez - dribeas
Sandeep
If you want shared semantics, you can just use `boost::shared_ptr` or `std::tr1::shared_ptr` or `std::shared_ptr` if your compiler has support for the TR1 extensions or C++0x mode respectively.
David Rodríguez - dribeas