I'd like to know do I need to write destructor in classes when I don't use raw pointers anymore? Just boost smart pointers.
Boost smart pointers by themselves don't have anything to do with the need for a destructor. All they do is remove the need for you to call delete on the allocated memory that they are effectively managing. So having said that, if before you started using smart pointers all you had in your destructors were calls to delete and delete[] freeing the memory of dynamically allocated class members and you have now switched all those regular pointers over to smart pointers, you could probably just switch to an empty destructor as they will now clean up for themselves when they go out of scope.
However, if for whatever reason, you have a class that needs to do cleanup (file cleanup, sockets, other resources etc) you will still need to provide a destructor to do that.
Let me know if that helps.
smart_ptr
. With C++11, class destructors should be rare - Mooing Duck 2012-04-03 20:16
Each resource type should have a RAII class to manage that resource. If you also have a smart pointer with deep copy semantics (pretty easy to do), that's all you need to manage your resources 99.9% of the time. I don't know why unique_ptr
doesn't do deep copies, nor any boost smart pointer, but if you have those two things, you do not need to write copy constructors, move constructors, assignment operators, move assignment operators, nor destructors. You may or may not have to provide other constructors (including the default constructor), but that's five less places to make mistakes.
#include <memory>
template<class Type, class Del = std::default_delete<Type> >
class deep_ptr : public std::unique_ptr<Type, Del> {
public:
typedef std::unique_ptr<Type, Del> base;
typedef typename base::element_type element_type;
typedef typename base::deleter_type deleter_type;
typedef typename base::pointer pointer;
deep_ptr() : base() {}
//deep_ptr(std::nullptr_t p) : base(p) {} //GCC no has nullptr_t?
explicit deep_ptr(pointer p) : base() {}
deep_ptr(pointer p, const typename std::remove_reference<Del>::type &d) : base(p, d) {} //I faked this, it isn't quite right
deep_ptr(pointer p, typename std::remove_reference<Del>::type&& d): base(p, d) {}
deep_ptr(const deep_ptr& rhs) : base(new Type(*rhs)) {}
template<class Type2, class Del2>
deep_ptr(const deep_ptr<Type2, Del2>& rhs) : base(new Type(*rhs)) {}
deep_ptr(deep_ptr&& rhs) : base(std::move(rhs)) {}
template<class Type2, class Del2>
deep_ptr(deep_ptr<Type2, Del2>&& rhs) : base(std::move(rhs)) {}
deep_ptr& operator=(const deep_ptr& rhs) {base::reset(new Type(*rhs)); return *this;}
template<class Type2, class Del2>
deep_ptr& operator=(const deep_ptr<Type2, Del2>& rhs) {base::reset(new Type(*rhs)); return *this;}
deep_ptr& operator=(deep_ptr&& rhs) {base::reset(rhs.release()); return *this;}
template<class Type2, class Del2>
deep_ptr& operator=(deep_ptr<Type2, Del2>&& rhs) {base::reset(rhs.release()); return *this;}
void swap(deep_ptr& rhs) {base::swap(rhs.ptr);}
friend void swap(deep_ptr& lhs, deep_ptr& rhs) {lhs.swap(rhs.ptr);}
};
With this class (or one similar), you don't need much at all!
struct dog {
deep_ptr<std::string> name;
};
int main() {
dog first; //default construct a dog
first.name.reset(new std::string("Fred"));
dog second(first); //copy construct a dog
std::cout << *first.name << ' ' << *second.name << '\n';
second.name->at(3) = 'o';
std::cout << *first.name << ' ' << *second.name << '\n';
second = first; //assign a dog
std::cout << *first.name << ' ' << *second.name << '\n';
}
As demonstrated at http://ideone.com/Kdhj8
You should always consider providing a destructor. You would use that to free any resources your class is holding. Often my smart_ptr class destructors are empty but not always. File streams, database connections, etc all need proper cleanup.
smart_ptr
. With C++11, class destructors should be rare - Mooing Duck 2012-04-03 20:15