Smart pointers and destructor

I would like to know if I need to write a destructor in classes when I no longer use raw pointers? Just raise smart pointers.

+6
source share
3 answers

Raising smart pointers alone has nothing to do with the need for a destructor. All they do is remove the need to cause deletion in the allocated memory, which they effectively manage. Therefore, having said this, if before you started using smart pointers, all that you had in your destructors were calls to delete and delete [] free the memory of dynamically allocated class members, and now you have switched all these ordinary pointers to smart pointers, you could possibly just switch to an empty destructor, since they will now be cleared for themselves when they go out of scope.

However, if for some reason you have a class that needs to perform cleaning (cleaning files, sockets, other resources, etc.), you still need to provide a destructor for this.

Let me know if this helps.

+10
source

Each resource type must have an RAII class to manage this resource. If you also have a smart pointer with deep copy semantics (quite easy to do), all you need to manage your resources in 99.9% of cases. I do not know why unique_ptr does not make deep copies and does not raise the smart pointer, but if you have these two things, you do not need to write copy constructors, move constructors, assignment operators, move assignment operators and destructors. You may need to provide other constructors (including the default constructor), but there are five more places for errors.

 #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 like that) you don't need to 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 shown at http://ideone.com/Kdhj8

+4
source

You should always consider creating a destructor. You would use this to free the resources your class owns. Often my smart_ptr class destructors are empty, but not always. File streams, database connections, etc. Needs proper cleaning.

-2
source

Source: https://habr.com/ru/post/912336/


All Articles