stack/hopr

writing between 0 and 1

Archive for the ‘Programming’ tag

Smart Ptr [v2]

with one comment

I have to admit. The first version was put together hastily. With the feedback considered, here’s the second version. Again, the goal of simplicity and no dependency have been adhered to.

Thanks to Andrew, vlademar, Ben, schula and Desu for the quick comments.

Feedback goes like this:

1. No default copy constructor. So, the compiler will provide one and it allows the smart_ptr to be copied to another smart_ptr. It might make the pointer propagate out of scope / trigger multiple deallocations.
A. Facing a design dilemma here.

I have to forbid the assignments. So, I make the assignment operator and the copy constructor private.
Like this:

1. public:     smart_ptr(T* p):ptr(p) {}
2. private:     smart_ptr(smart_ptr& s):ptr(NULL) {}

It’s interesting to note that as long as both the above functions are public,

smart_ptr<myclass> s = new myclass;

calls the first function, which is NOT a copy constructor.

But, if i make the second function private, the compilation fails stating that the copy constructor is private.

Is there anyway, I can make copying a compile time offence and also maintain ability to do ” = new myclass”? Because, I think declaring a variable and initializing it on the same line is the fundamental right of a programmer. Nobody takes it away.

2. No assignment operator. the compiler will provide a default one. And then, same problem as above.
A. Assignment operator declared private.

3. No need to check if pointer in null before deleting it.
A. Extra check removed.

4. Use of “NULL” in place of “0″.
A. I would like to retain it for readability.

5. Why am I writing this class when we already have auto_ptr (STL) and scoped_ptr (boost)?
A. More than anything else, simplicity. Simple enough, for use in local allocations. Second, no dependency on any other library might make sense when you’re writing for embedded systems. Some libraries just may not be available there. Finally, education. Helps new folks learn what’s happening behind the scenes.

6. Const overloads for dereference and arrow operators is needed.
A. The dereference operator and the arrow operator are now aptly const.

7. Throw something derived from std::exception.
A. To keep things small (as in bullet 5), I’m skipping this. Although, I defined a constant “null_pointer_reference” for throwing and catching.

8. The dereferencing operator should throw somthing rather than returning NULL.
A. Yes, it compiles. Throws an exception now.

Code for smart_ptr class (v2) follows:

template<typename T>
class smart_ptr

{
public:
	T* operator->()	const {if(ptr) return ptr; throw null_pointer_reference;}

	T& operator*() const {if(ptr) return *ptr; throw null_pointer_reference;}

	smart_ptr():ptr(NULL) {}

	smart_ptr(T* p):ptr(p) {}

	~smart_ptr() {delete(ptr); ptr = NULL;}		

	smart_ptr& operator=(T* p) {delete(ptr); ptr = p; return *this;}

private:
	smart_ptr& operator=(const smart_ptr& s) {}

	//smart_ptr(smart_ptr& s):ptr(NULL) {}	
protected:
	T* ptr;
};

The complete program (with test cases) is here: smart.cpp.

Written by Amol

November 11th, 2008 at 12:41 pm

Posted in Programming,code

Tagged with , , ,