lundi 23 novembre 2015

why unique_ptr can be used in STL container, but auto_ptr cannot?

Thanks in advance.

I don't mean to ask a duplicate quesion here. But I still quite not understand the reason why unique_ptr can be used in STL container, but auto_ptr cannot, after reading the following related links

Why a unique_ptr can be used with std containers, vectors<> for example?

Advantages of unique_ptr over auto_ptr?

So can unique_ptr be used safely in stl collections?

Why is it wrong to use std::auto_ptr<> with standard containers?

Difference:

auto_ptr: has weird copy constructor, null the ptr of object being copied

unique_ptr: has no copy constructor, but has move constructor

Quesion 1:

Please refer to the following code, it seems that the results are totally same, ownership is changed in both case. I know auto_ptr will transfer the ownership implicitly, but unique_ptr will transfer ownership explicitly. From this example, why we can confirm that unique_ptr can be used in STL, but auto_ptr cannot.

class X
{
};
// auto_ptr
std::vector<std::auto_ptr<X> > vec1;
vec1.push_back(new X);

std::auto_ptr<X> p1 = vec1[0];  // vec1[0] is assigned NULL.

// unique_ptr
std::vector<std::unique_ptr<X> > vec2 ;
vec2.push_back( std::move(new X) );

std::unique_ptr<X> p2 = std::move( vec1[0] );  // vec2[0] is assigned NULL.

Quesion 2:

In Effective STL item 9, Scott Meyers said in sort function, the pivot choosen operation will null the auto_ptr in vector. But what if the case that we use unique_ptr, the effect still happens I believe, because ownership will be changed. In fact, I believe the real implemention in sort function will use swap. I think both auto_ptr and unique_ptr support swap operation in STL, right?

Emulate the swap operation, but what is difference below?

// auto_ptr
auto_ptr<int> p1 (new int(1));
auto_ptr<int> p2 (new int(2));
auto_ptr<int> temp;
temp = p1; // p1 becomes nullptr, temp becomes p1
p1 = p2;// p2 becomes nullptr
p2 = temp;//p2 becomes  p1

// unique_ptr
unique_ptr<int> p1 (new int(1));
unique_ptr<int> p2 (new int(2));
unique_ptr<int> temp;
temp = std::move(p1);// p1 becomes nullptr, temp becomes p1
p1 = std::move(p2);// p2 becomes nullptr
p2 = std::move(temp);//p2 becomes  p1

Aucun commentaire:

Enregistrer un commentaire