Vaska el gato
Vaska el gato

Reputation: 198

Why auto_ptr initialization using the assignment syntax is not allowed

I was reading through this book C++ standard library book

And here is the part i can not understand:

Note that class auto_ptr<> does not allow you to initialize an object with an ordinary pointer by using the assignment syntax.

std::auto_ptr<ClassA> ptr1(new ClassA); //ok
std::auto_ptr<ClassA> ptr2 = new ClassA; //error

I don't understand why it is not allowed. What kind of pitfalls they were trying to avoid by not allowing initialization with assignment syntax

Upvotes: 3

Views: 1698

Answers (3)

songyuanyao
songyuanyao

Reputation: 173004

  1. I don't understand why it is not allowed.

At first direct initialization and copy initialization are not the same thing.

std::auto_ptr<ClassA> ptr1(new ClassA); //ok

This is direct initialization.

std::auto_ptr<ClassA> ptr2 = new ClassA; //error

This is copy initialization.

Copy-initialization is less permissive than direct-initialization: explicit constructors are not converting constructors and are not considered for copy-initialization.

So if you want to initialize std::auto_ptr with raw pointer via copy initialization, converting constructor will be needed, but std::auto_ptr doesn't have it.

std::auto_ptr's constructor taking one raw pointer as parameter is explicit, implicit conversion is prohibited.

  1. What kind of pitfalls they were trying to avoid by not allowing initialization with assignment syntax

Consider about the following code if implicit conversion is allowed:

void f1(ClassA* p) { ... }
void f2(std::auto_ptr<ClassA> p) { ... }
...
ClassA* p = new ClassA;
f2(p);           // call the wrong function, ownership is transfered to auto_ptr implicitly
p->something(); // UB, p has been deleted
delete p;       // UB

Upvotes: 2

Benjamin Lindley
Benjamin Lindley

Reputation: 103741

The fact that the assignment syntax cannot be used to initialize an auto_ptr from a raw pointer is a side effect of the constructor which takes a raw pointer being marked explicit. And the usual reason to mark a constructor as explicit is to prevent things like this:

void take_ownership(std::auto_ptr<ClassA> ptr) {
    // the pointer is deleted when this function ends
}

void foo() {
    ClassA obj;
    take_ownership(&obj); // oops, delete will be called on a pointer to
                          // an object which was not allocated with new
}

The call to the take_ownership function is an error there, because of the explicit classifier on the std::auto_ptr constructor. Instead, you have to deliberately construct an auto_ptr and pass that to the function.

void foo() {
    std::auto_ptr<ClassA> ptr(new ClassA);
    take_ownership(ptr); // okay
}

Of course this is not completely impervious to abuse (you can still pass a non-newed object to the constructor of auto_ptr), it is at least easier to spot when an abuse is taking place.

By the way, std::auto_ptr is deprecated. It is a very broken class (due to limitations in the language at the time it was introduced). Use std::unique_ptr instead.

Upvotes: 6

chenzhongpu
chenzhongpu

Reputation: 6871

Here is how std::auto_ptr defined:

template< class T > class auto_ptr;
template<> class auto_ptr<void>;

Hence auto_ptr is a class type. Let's see its constructors:

explicit auto_ptr( X* p = 0 );
auto_ptr( auto_ptr& r );
template< class Y >
auto_ptr( auto_ptr<Y>& r );
template< class Y >
auto_ptr( auto_ptr_ref<Y> m );

Consider the first constructor. we can use a pointer to X type object as parameter to call this constructor:

std::auto_ptr<X> ptr1(new X); //ok

In the meanwhile, this first constructor is explicit, hence we cannot use a pointer to X type object implicitly to transform to auto_ptr<X>. In other words, we cannot initialize directly it via a pointer to X type object.

    std::auto_ptr<X> ptr1 = new X; //error; cannot implicitly transform

Upvotes: 2

Related Questions