Smart Pointer Operator =

I saw several smart pointers that implement operator= two ways:

A) One that assigns a raw pointer to another raw pointer:

 SmartPointer& operator=(const SmartPointer& rhs) { delete m_ptr; m_ptr = rhs.m_ptr; return *this; } 

B) And the one that resets the right side pointer after assignment:

 SmartPointer& operator=(SmartPointer& rhs) { delete m_ptr; m_ptr = rhs.m_ptr; rhs.m_ptr = nullptr return *this; } 

My question will be , which is recommended to use ? My problem with B) is that if you want to continue working with the second smart pointer (see the code below), the program will crash (if you do not check the null pointer) or do nothing. And it doesn’t seem too pleasant :)

 SmartPointer<MyClass> p1(new MyClass()); SmartPointer<MyClass> p2(new MyClass()); p1 = p2; p2->someMethod(); // <----- BOOM! 
+6
source share
1 answer

Introduction

If you want your smart pointer to be copied, the declaration (A) is fine; just remember that you cannot free memory twice, which means there must be some way to show that the copied smart pointer does not actually own the resource it refers to.


Danger, DANGER!

Declaration (B), however, is erroneous because it does not correspond to any semantics that are inside the language; It is strange that the right side, which lives outside the operation, changes when it acts as a simple source of the task.

If you plan on moving data from one side to the other, you must use an overload that accepts an rvalue reference. The specified link can only be attached to a temporary one or to what is explicitly indicated as acting as one (that is, what the developer knows, may have an undefined value after the operation).

rvalue references were introduced in C ++ 11, and the implementation might look like this.

 SmartPointer& operator=(SmartPointer&& rhs) // (B), move assign { delete m_ptr; // release currently held resource m_ptr = rhs.m_ptr; // assign new resource rhs.m_ptr = nullptr; // prevent `rhs` from deleting our memory, it no longer in charge return *this; } 
 SmartPointer<MyClass> p1(new MyClass()); SmartPointer<MyClass> p2(new MyClass()); p1 = p2; // ill-formed, (B) is not applicable; cannot bind lvalue to rvalue reference p1 = std::move (p2) // legal 

What is the standard?

In the C ++ 11 library, std::unique_ptr , std::shared_ptr and std::weak_ptr .

An examination of their implementation should serve as an excellent understanding of how smart pointers work, and how differences in semantics determine differences in written code.

+6
source

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


All Articles