Can you forget about checkout when using C ++ 11 smart pointers?

I read about unique_ptr with incomplete types and about Checked Delete , But is it checked to delete obsolete when using smart pointers or at least a subset of C ++ 11 smart pointers?

Take the following code:

class A; class B { public: std::auto_ptr<A> autoPtr; std::unique_ptr<A> uniquePtr; std::shared_ptr<A> sharedPtr; A* rawPtr; B(); ~B(){delete rawPtr;} }; class A { public: ~A(){std::cout << "~A" << std::endl;} }; B::B() { autoPtr = std::auto_ptr<A>(new A()); uniquePtr = std::unique_ptr<A>(new A()); sharedPtr = std::shared_ptr<A>(new A()); rawPtr = new A(); } B b; 

When a B destructor is defined, type A is still incomplete. As far as I know [C ++ 11 standard @ [expr.delete]], deleting the original pointer has undefined behavior. On my machine, gcc 4.8 shows some warnings about this, but it also compiles and the destructor A is not called properly.

But what about smart pointers? As I read, unique_ptr and shared_ptr should work in accordance with the C ++ 11 standard. But in both related documents it is indicated that auto_ptr will not work. But at least with my gcc 4.8, auto_ptr correctly calls the destructor without warning. Is this behavior undefined and gcc just nice?

In short: Which of the four member variables is guaranteed to destroy their A-pointer, using its later-defined destructor correctly, in accordance with the C ++ 11 standard?

And finally: If I use only unique_ptr and shared_ptr and never call delete on my own, am I sure and should never think of a โ€œdelete checkโ€ again?

+6
source share
1 answer

For shared_ptr it matters whether the type is terminated when you pass a pointer to shared_ptr (which should usually be because you just created A ). At this point, shared_ptr will create some kind of debiter that needs the full type, and save it so that it is available when the reference count drops to zero (even if it happens in a file where A is incomplete).

For unique_ptr it is important whether this type is completed when default_delete called, which will usually be in the unique_ptr destructor (but it can also be in its reset() member or assignment operation).

Using auto_ptr with incomplete types is just undefined.

To answer the question in the header: the standard requires that shared_ptr and unique_ptr refuse to compile code that tries to remove an incomplete type. This does not guarantee 100% security, because when executing unique_ptr<base>(new derived) , the behavior may be undefined if base does not have a virtual destructor.

I believe that the execution of the code to compile the code is that GCC creates the templates at the end of the file, and the inline B destructor is not needed until B is defined, and then point A completed. If you put the definition of A and B::B into a separate file from the variable B , you will find that unique_ptr will not correctly delete A when B is destroyed (in fact, this does not even compile, since destroying B calls default_delete , and the standard states that a full type is required or the program is poorly formed).

A portable solution is to ensure the completion of A , where you define a destructor for B , so do not specify a built-in destructor if A not filled in all files.

+4
source

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


All Articles