Smart pointers

Hi,

Please have a look at the code below. Is this a smart pointer?
If so, why the first object, p1, is dangling at the end of the code? (That is p2 is deleted by the destructor but p1 remains, why?)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <vector>
using namespace std;

template <class T> class my_auto_ptr {
	T* myptr;

public:
	my_auto_ptr(T* ptr = 0) : myptr(ptr) { }

	~my_auto_ptr() {
		delete myptr;
	}

	T* operator ->() const {
		if (myptr != nullptr)  return myptr;
		else throw runtime_error("");
	}
	T& operator* () const {
		if (myptr != nullptr)  return *myptr;
		else throw runtime_error("");
	}
	T* release() {
		T* rptr = myptr;
		myptr = 0;
		return rptr;
	}
};

//----------------------------------

int main() try {
	my_auto_ptr<vector<int> > p1(new vector<int>(4, 5));
	cout << p1->size() << endl;

	my_auto_ptr<int> p2(new int(6));
	cout << *p2 << endl;
	
	return 0;
}

//-------------------------------

catch (...) {
	cerr << "Exception occurred.\n";
	return 1;
}
Last edited on
If so, why the first object, p1, is dangling at the end of the code? (That is p2 is deleted by the destructor but p1 remains, why?)

What makes you think this is the case?
I think it has sth. do to with scope. If you wrap the code with the pointer in their own block they will get out of scope before main end.

Try this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <vector>
using namespace std;

template <class T> class my_auto_ptr
{
  T* myptr;

public:
  my_auto_ptr (T* ptr = 0) : myptr (ptr) { }

  ~my_auto_ptr () 
  {
    cout << "\n** my_auto_ptr::~my_auto_ptr() **";
    delete myptr;
  }

  T* operator ->() const 
  {
    if (myptr != nullptr)  return myptr;
    else throw runtime_error ("");
  }
  T& operator* () const 
  {
    if (myptr != nullptr)  return *myptr;
    else throw runtime_error ("");
  }
  T* release () 
  {
    T* rptr = myptr;
    myptr = 0;
    return rptr;
  }
};

//----------------------------------

int main () 
{
  try
  {
    {
      my_auto_ptr<vector<int> > p1 (new vector<int> (4, 5));
      cout << p1->size () << endl;

      my_auto_ptr<int> p2 (new int (6));
      cout << *p2 << endl;
    }
    system ("pause");
    return 0;
  }
  catch (...)
  {
    cerr << "Exception occurred.\n";
    system ("pause");
    return 1;
  }  
}
Your question makes no sense.

Both of your custom my_auto_ptr type objects are destructored. In doing so, both of them call delete on the objects you created with new.

As Peter asked, why do you think this isn't happening?
@Moschops,

did you run his code?

When I ran it on my VS 2013 CE the destructor's were not called - added a cout statement in his destructor.
On my VS2015 the destructor is called as expected for both pointers.
@Thomas1965: Yes, I agree.
And to me it's not a smart pointer enough, because we need to add a block for every pointer we create.
My compiler is MS VS 2015. And I ran the code through "Run To Cursor" mode.
Thanks to all.
Best way to find out if you're destructor is being called for both objects?

Do this:

Add a cout statement saying "Destructing auto_ptr" inside your destructor. Next, run your program from the COMMAND PROMPT in windows. This console won't close and you'll get to see the destructor output. You should see two destructor lines, indicating that it was called twice - once for each auto_ptr.

Try it.

Joe
Concord Spark Tutor
sparkprogrammer@gmail.com
@Thomas1965

I cannot imagine that such a basic C++ concept like destructor doesn't work correctly with any recent compiler (including VS 2013).
@coder777,

I didn't say that it didn't work. I meant that when it went out of scope there that the console was closed already. That's the reason why I added the additional scope to see a result. When using a logfile it clearly show that both destructors were called.
Sorry if I was not clear enough, but English is not my native language.
The fundamental concept of C++ is that the destructor is called when an object falls out of the scope where the constructor is called.

That means when an exception arise during or before the constructor is called the destructor isn't called either. Thus it is possible due to an exception that the destructor is not called.
You guys, are right. I added the system ("pause"); inside the destructor's body and it showed that the destructor was called for both pointers. Even when I created another object, for this one too, the destructor was called. And also there is no need to add any redundant blocks.
Apparently we cannot only rely on the "Run To Cursor" feature for seeing what is happening. Thanks.
Topic archived. No new replies allowed.