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参照