- 使用类模板,可以智能管理任何类型的指针
- 要实现指针的相关行为:
operator *
、opeartor->
、operator bool()
、++
、--
等。 - 特别要注意拷贝赋值(operatro=)的实现,如何保证异常安全。
- 注意实现swap
- 在
UniquePointer
中使用移动赋值函数,来代替普通的拷贝赋值函数,实现所有权转移是更优的做法。 UniquePointer
中定义了移动构造函数,编译器就不会再定义拷贝构造函数了,所以对于UniquePointer
来说,拷贝构造函数相当于=delete
了。- 如果要实现通过派生类的智能指针来构造基类的智能指针,就需要加入一个模板的拷贝构造方法。而且编译器不会认为模板方法是拷贝构造方法,需要额外再定义一个非模板的拷贝构造,不然编译器就自动生成了,对于
SharedPointer
来说,自动生成的,肯定是不对的。
关于为何使用移动改善了auto_ptr
的行为,实现了与unique_ptr
相近的语义,这里的“改善”是否应该这样理解:
在没有引入右值引用和移动构造的情况下,构造的auto_ptr
也能工作,但是会令用户困惑,当用户执行了语句other_ptr = some_ptr
后,some_ptr
就为空了。
引入右值引用和移动构造后,用户要想用重载的operator=
,必须采用other_ptr = std::move(some_ptr)
的方式,通过显示调用std::move
,让用户aware到some_ptr
的内容已经被移动到other_ptr
了,并且同时默认禁用了参数为左值引用的拷贝构造,导致other_ptr = some_ptr
无法通过编译,就不会在使用时产生歧义了,这就是unique_ptr
期望的语义。
另外额外加一点,调用移动不一定靠move
。如果函数返回一个unique_ptr
一样是自然的移动。
SharedPointer
的拷贝构造函数为什么有一个泛型版本还有一个非泛型版本 但是函数体内容又一模一样,不是代码冗余的吗,是有什么特殊设计意图吗?
如果没有非泛型版本,编译器看到没有拷贝构造函数,会生成一个缺省的拷贝构造函数。这样,同样类型的smart_ptr
的拷贝构造会是错误的。