Update item18.md

This commit is contained in:
猫耳堀川雷鼓
2021-02-16 16:08:39 +08:00
committed by GitHub
parent a0d0024be3
commit 61fc892016

View File

@@ -31,7 +31,7 @@
`std::unique_ptr`体现了专有所有权(*exclusive ownership*语义。一个non-null `std::unique_ptr`始终拥有其指向的内容。移动一个`std::unique_ptr`将所有权从源指针转移到目的指针。源指针被设为null。拷贝一个`std::unique_ptr`是不允许的,因为如果你能拷贝一个`std::unique_ptr`,你会得到指向相同内容的两个`std::unique_ptr`,每个都认为自己拥有(并且应当最后销毁)资源,销毁时就会出现重复销毁。因此,`std::unique_ptr`是一种只可移动类型(*move-only type*。当析构时一个non-null `std::unique_ptr`销毁它指向的资源。默认情况下,资源析构通过对`std::unique_ptr`里原始指针调用`delete`来实现。
`std::unique_ptr`的常见用法是作为继承层次结构中对象的工厂函数返回类型。假设我们有一个investment类型比如stocksbondsreal estate等)的继承结构,使用基类`Investment`
`std::unique_ptr`的常见用法是作为继承层次结构中对象的工厂函数返回类型。假设我们有一个投资类型(比如股票、债券、房地产等)的继承结构,使用基类`Investment`
```cpp
class Investment { };
@@ -61,9 +61,9 @@ makeInvestment(Ts&&... params);
} //销毁 *pInvestment
```
但是也可以在所有权转移的场景中使用它,比如将工厂返回的`std::unique_ptr`移入容器中,然后将容器元素移入一个对象的数据成员中,然后对象过后被销毁。发生这种情况时,这个对象的`std::unique_ptr`数据成员也被销毁,并且智能指针数据成员的析构将导致销毁从工厂返回的资源。如果所有权链由于异常或者其他非典型控制流出现中断比如提前从函数return或者循环中的`break`),则拥有托管资源的`std::unique_ptr`将保证指向内容的析构函数被调用,销毁对应资源。(这个规则也有些例外。大多数情况发生于不正常的程序终止。如果一个异常传播离开线程的基本函数(比如程序初始线程的`main`函数),或者违反`noexcept`说明(见[Item14](https://github.com/kelthuzadx/EffectiveModernCppChinese/blob/master/3.MovingToModernCpp/item14.md)),局部变量可能不会被销毁;如果`std::abort`或者退出函数(如`std::_Exit``std::exit`,或`std::quick_exit`)被调用,局部变量一定没被销毁。)
但是也可以在所有权转移的场景中使用它,比如将工厂返回的`std::unique_ptr`移入容器中,然后将容器元素移入一个对象的数据成员中,然后对象过后被销毁。发生这种情况时,这个对象的`std::unique_ptr`数据成员也被销毁,并且智能指针数据成员的析构将导致从工厂返回的资源被销毁。如果所有权链由于异常或者其他非典型控制流出现中断比如提前从函数return或者循环中的`break`),则拥有托管资源的`std::unique_ptr`将保证指向内容的析构函数被调用,销毁对应资源。(这个规则也有些例外。大多数情况发生于不正常的程序终止。如果一个异常传播线程的基本函数(比如程序初始线程的`main`函数),或者违反`noexcept`说明(见[Item14](https://github.com/kelthuzadx/EffectiveModernCppChinese/blob/master/3.MovingToModernCpp/item14.md)),局部变量可能不会被销毁;如果`std::abort`或者退出函数(如`std::_Exit``std::exit`,或`std::quick_exit`)被调用,局部变量一定没被销毁。)
默认情况下,销毁将通过`delete`进行,但是在构造过程中,`std::unique_ptr`对象可以设置使用对资源的**自定义删除器**:当资源需要销毁时可调用的任意函数(或者函数对象,包括*lambda*表达式)。如果通过`makeInvestment`创建的对象不应仅仅被`delete`,而应该先写一条日志,`makeInvestment`可以实现如下。(代码后有说明,别担心有些东西的动机不那么明显。)
默认情况下,销毁将通过`delete`进行,但是在构造过程中,`std::unique_ptr`对象可以设置使用对资源的**自定义删除器**:当资源需要销毁时可调用的任意函数(或者函数对象,包括*lambda*表达式)。如果通过`makeInvestment`创建的对象不应仅仅被`delete`,而应该先写一条日志,`makeInvestment`可以以如下方式实现。(代码后有说明,别担心有些东西的动机不那么明显。)
```cpp
auto delInvmt = [](Investment* pInvestment) //自定义删除器