mirror of
https://github.com/CnTransGroup/EffectiveModernCppChinese.git
synced 2026-08-19 16:03:30 +08:00
Update item18.md
This commit is contained in:
@@ -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类型(比如stocks,bonds,real 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) //自定义删除器
|
||||
|
||||
Reference in New Issue
Block a user