C++核心准则边译边学-I.11 永远不要使用原始指针或引用传递所有权

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++核心准则边译边学-I.11 永远不要使用原始指针或引用传递所有权相关的知识,希望对你有一定的参考价值。


I.11: Never transfer ownership by a raw pointer (​​T*​​​) or reference (​​T&​​)(永远不要使用原始指针或引用传递所有权)

Reason(原因)

If there is any doubt whether the caller or the callee owns an object, leaks or premature destruction will occur.

如果一个对象是属于调用者还是被调用者存在任何疑问的话,就可能发生泄漏或过早销毁。

Example(示例)

Consider:(考虑)

 

X* compute(args)    // dont

X* res = new X;
// ...
return res;


 


Who deletes the returned ​​X​​​? The problem would be harder to spot if ​​compute​​ returned a reference. Consider returning the result by value (use move semantics if the result is large):

应该由谁删除返回的X? 当compute返回一个参照的时候,这个问题会很难判断。考虑返回一个值(如果结果很大则使用移动语法)

译者注:移动语法指的是C++11开始引入的右值引用和std::move。进一步信息请参照下面的文章:

​https://mp.weixin.qq.com/s/MO4oxf5KjLRvpAvyyOMZiA​

​https://mp.weixin.qq.com/s/WNVUfG11aTZ9bq6lBtaCyg​

 

vector<double> compute(args)  // good

vector<double> res(10000);
// ...
return res;


 


Alternative: Pass ownership using a "smart pointer", such as ​​unique_ptr​​​ (for exclusive ownership) and ​​shared_ptr​​ (for shared ownership). However, that is less elegant and often less efficient than returning the object itself, so use smart pointers only if reference semantics are needed.

其他选项:使用“智能指针”传递所有权,例如unique_ptr(用于独占所有权)和shared_prt(用于共享所有权)。然而这种做法和直接返回对象本身相比稍微欠缺一点优雅和效率,因此应该只在需要参照语义时才需要智能指针。

译者注:智能指针可以参考以下文章。

shared_ptr:

​https://mp.weixin.qq.com/s/rreUOPpoNTvPWXLjgV_bsA​

​https://mp.weixin.qq.com/s/3J1_nZNrDs5X-rw_XUw9UQ​

​https://mp.weixin.qq.com/s/hURdinSkkw960qD5Wq1YOA​

unique_ptr:

​https://mp.weixin.qq.com/s/wgc8p1Pw9GD5LIx1C33wxQ​

 

Alternative: Sometimes older code cant be modified because of ABI compatibility requirements or lack of resources. In that case, mark owning pointers using ​​owner​​ from the guidelines support library:

其他选项:有时因为ABI兼容性的要求或者需要避免资源泄漏而无法修改旧代码。在这种情况下,使用准则支持库提供的owner形式来标记控制所有权的指针。

译者注:ABI,由操作系统提供的应用程序二进制接口(Application Binary Interface)

 

owner<X*> compute(args)    // It is now clear that ownership is transferred

owner<X*> res = new X;
// ...
return res;


 


This tells analysis tools that ​​res​​​ is an owner. That is, its value must be ​​delete​​​d or transferred to another owner, as is done here by the ​​return​​.

这样可以告诉分析工具res是所有者。也就是说,它的值必须被删除或者转移给其他的所有者,就像这里通过return返回结果时所做的一样。

​owner​​ is used similarly in the implementation of resource handles.

在实现资源句柄的时候,owner也会以相似的方式被使用。

Note(注意)

Every object passed as a raw pointer (or iterator) is assumed to be owned by the caller, so that its lifetime is handled by the caller. Viewed another way: ownership transferring APIs are relatively rare compared to pointer-passing APIs, so the default is "no ownership transfer."

所有通过原始指针(或迭代器)传递的对象都被假设由调用者所有,因此它的生命周期也由调用者管理。换一个角度:相对而言,和指针传递API相比,所有权转移API相当少,因此(大家)默认的情况是没有所有权转移。

See also: Argument passing, use of smart pointer arguments, and value return.

参考:参数传递,使用智能指针参数,值返回。

Enforcement(实施建议)

  • (Simple) Warn on ​​delete​​​ of a raw pointer that is not an ​​owner<T>​​​. Suggest use of standard-library resource handle or use of ​​owner<T>​​.

(简单)在删除原始指针而不是owner<T>时报警。建议使用标准库中的资源句柄或者owner<T>

  • (Simple) Warn on failure to either ​​reset​​​ or explicitly ​​delete​​​ an ​​owner​​ pointer on every code path.

(简单)如果任何代码路径上的owner指针的重置或删除操作发生失败,报警。

  • (Simple) Warn if the return value of ​​new​​​ or a function call with an ​​owner​​​ return value is assigned to a raw pointer or non-​​owner​​ reference.

(简单)如果new或者返回owner的函数调用的结果被分配给原始指针或者非owner引用,报警。

以上是关于C++核心准则边译边学-I.11 永远不要使用原始指针或引用传递所有权的主要内容,如果未能解决你的问题,请参考以下文章

C++核心准则边译边学-F.17 输入/输出参数传递非常量引用

C++核心准则边译边学-F.16 对于输入参数来说,拷贝代价小的传值,其他传递const参照

C++核心准则F.55 不要使用可变参数

C++核心准则F.54:不要隐式捕捉this指针

C++核心准则C.7:不要在一条语句内声明类或枚举值的同时又定义该类型的变量

c++的核心准则