首页 > 试题广场 >

请你说一下你理解的c++中的smart pointer四个智

[问答题]

请你说一下你理解的c++中的smart pointer四个智能指针:

shared_ptr,unique_ptr,weak_ptr,auto_ptr

auto_ptrunique_ptr不说移动语义?

C++11之前没有移动的说法,因此auto_ptr只能凡复制就转移所有权。新引入了右值引用和移动语义之后,unique_ptr禁止复制构造,只能移动构造,避免了auto_ptr的问题。转移所有权只能自己写p2 = std::move(p1),写了个如此显眼的move之后还要自己去访问p1只能说手贱没治。

另外shared_ptr允许shared_ptr<void>来管理任何类型指针并且确保正确析构(但是unique_ptr是不行的),这是因为shared_ptr的管理块中存储了类型擦除后的Deleter用来析构。在C++标准中它和unique_ptr的声明是不一样的:

template  class shared_ptr;
template <class T, 
          class Deleter = std::default_delete<T>
> class unique_ptr;
template 
class unique_ptr; 

std::default_delete就是纯粹包装了一下delete/delete[]

shared_ptr不带Deleter模板参数而unique_ptr带,与之对应shared_ptr的构造函数中是可以自行提供Deleterunique_ptr不行(而且shared_ptr的构造函数是模板函数)。那么只要shared_ptr<void>在构造的时候,根据传入的指针类型推断出正确的Deleter保存下来,在析构的时候调用即可实现正确析构。

与之同理,在处理继承的情况时,shared_ptr<Base> p{ new Derived() }也能正确调用Derived的析构函数,即使析构函数不是virtual的。同样unique_ptr不支持这种行为,非virtual析构函数情况下,不手动指定Deleter(也即std::unique_ptr<Base, std::default_delete<Derived>> p{ new Derived() })的话它只会调用~Base

最后,因为shared_ptr支持这些复杂功能,因此其中的管理块存储的不只是一个引用计数。所以在创建新的shared_ptr的时候不要直接调用构造函数,传入的对象一次new,管理块一次new,两次内存申请。无特殊情况应该用std::make_shared<T>,只会申请一次内存。unique_ptr没有这个问题,用构造函数或者C++14为了形式上统一引进的std::make_unique<T>都是可以的。

编辑于 2019-08-29 11:39:05 回复(0)