R.3: A raw pointer (a T*) is non-owning

R.3: 原始指针(T*)不应拥有所有权

Reason(原因)

There is nothing (in the C++ standard or in most code) to say otherwise and most raw pointers are non-owning. We want owning pointers identified so that we can reliably and efficiently delete the objects pointed to by owning pointers.

这一点不存在任何例外(无论是C++标准还是大部分代码)而且大多数原始指针就是没有所有权的。我们需要所有权指针被定义出来,这样就可以可靠地,高效地删除所有权指针指向的对象。

Example(示例)

void f()
{int* p1 = new int{7};           // bad: raw owning pointerauto p2 = make_unique<int>(7);  // OK: the int is owned by a unique pointer// ...
}

The unique_ptr protects against leaks by guaranteeing the deletion of its object (even in the presence of exceptions). The T* does not.

unique_ptr通过(即使在发生异常的情况下)保证对象的删除来防止内存泄露。而T*不会。

Example(示例)

template<typename T>
class X {
public:T* p;   // bad: it is unclear whether p is owning or notT* q;   // bad: it is unclear whether q is owning or not// ...
};

We can fix that problem by making ownership explicit:

我们可以通过明确地赋予所有权来解决这个问题。

template<typename T>
class X2 {
public:owner<T*> p;  // OK: p is owningT* q;         // OK: q is not owning// ...
};

Exception(例外)

A major class of exception is legacy code, especially code that must remain compilable as C or interface with C and C-style C++ through ABIs. The fact that there are billions of lines of code that violate this rule against owning T*s cannot be ignored. We'd love to see program transformation tools turning 20-year-old "legacy" code into shiny modern code, we encourage the development, deployment and use of such tools, we hope the guidelines will help the development of such tools, and we even contributed (and contribute) to the research and development in this area. However, it will take time: "legacy code" is generated faster than we can renovate old code, and so it will be for a few years.

例外主要来源于既有代码,特别是那些由于ABIs必须保持C兼容性或者包含C或C风格C++接口的情况。事实上存在成百万行的代码违反这条反对T*持有所有权的准则,它们不能被忽略。我们很高兴地看到软件工具可以将20年以上的老代码转换为崭新的现代C++代码,我们鼓励这类工具的开发、部署和使用,我们甚至向这个领域的研究做出了贡献,而且将继续做出贡献。然而这需要时间:“既有代码”的产生快于我们翻新旧代码的速度,因此这个过程将会持续一些年。

This code cannot all be rewritten (even assuming good code transformation software), especially not soon. This problem cannot be solved (at scale) by transforming all owning pointers to unique_ptrs and shared_ptrs, partly because we need/use owning "raw pointers" as well as simple pointers in the implementation of our fundamental resource handles. For example, common vector implementations have one owning pointer and two non-owning pointers. Many ABIs (and essentially all interfaces to C code) use T*s, some of them owning. Some interfaces cannot be simply annotated with owner because they need to remain compilable as C (although this would be a rare good use for a macro, that expands to owner in C++ mode only).

不可能所有的代码都被重写(即使存在优秀的转换软件),很快重写更不可能。这个问题不可能通过将所有具有所有权指针转换为unique_ptr和shared_ptr来解决,一部分的原因是基础的资源持有者需要/使用具有所有权的原始指针(同时也是简单指针)。例如,普通的vector实现包含一个所有权指针和两个非所有权指针。很多ABI(本质上讲所有面向C语言的接口)使用T*,其中有些具有所有权。因为需要维持C语言可编译,因此有些接口不能简单地加注所有权(虽然这是很少见的宏的好用法,它只是在C++模式时展开成为所有权指针)。

Note(注意)

owner<T*> has no default semantics beyond T*. It can be used without changing any code using it and without affecting ABIs. It is simply an indicator to programmers and analysis tools. For example, if an owner<T*> is a member of a class, that class better have a destructor that deletes it.

owner<T*>没有包含任何超过T*的语义。它不修改任何代码就可以使用而且不会影响ABI。它只是面向程序员和分析工具的一个指示信息。例如,如果owner<T*>是某类的成员,那个最好准备一个析构函数来销毁它。

Example, bad(反面示例)

Returning a (raw) pointer imposes a lifetime management uncertainty on the caller; that is, who deletes the pointed-to object?

返回一个(原始)指针会增加调用者生命周期管理的不确定性;即:谁应该销毁指针指向的对象?

Gadget* make_gadget(int n)
{auto p = new Gadget{n};// ...return p;
}void caller(int n)
{auto p = make_gadget(n);   // remember to delete p// ...delete p;
}

In addition to suffering from the problem from leak, this adds a spurious allocation and deallocation operation, and is needlessly verbose. If Gadget is cheap to move out of a function (i.e., is small or has an efficient move operation), just return it "by value" (see "out" return values):

这段代码可以排除来自内存泄漏问题的痛苦,但是增加了虚假的分配和释放操作和没有必要的冗长性。如果Gadget很容易移出函数(也就是说,很小或者存在高效的移动操作),直接只用传值(参照“输出“返回值)。

Gadget make_gadget(int n)
{Gadget g{n};// ...return g;
}

Note(注意)

This rule applies to factory functions.

这条准则适用于工厂函数。

Note(注意)

If pointer semantics are required (e.g., because the return type needs to refer to a base class of a class hierarchy (an interface)), return a "smart pointer."

如果需要指针语义(例如因为返回的指针需要指向类层次中的基类(某个接口)),返回一个智能指针。

Enforcement(实施建议)

  • (Simple) Warn on delete of a raw pointer that is not an owner<T>.

  • (简单)警告销毁owner<T>类型之外的原始指针的情况。

  • (Moderate) Warn on failure to either reset or explicitly delete an owner<T> pointer on every code path.

  • (中等)如果没有在所有代码路径上重置或者销毁onwer<T>指针,发出警告。

  • (Simple) Warn if the return value of new is assigned to a raw pointer.

  • (简单)如果new的返回值赋给原始指针,发出警告。

  • (Simple) Warn if a function returns an object that was allocated within the function but has a move constructor. Suggest considering returning it by value instead.、

  • (简单)如果一个函数返回的对象在函数内分配内存,但是包含移动构造函数。提出建议通过传值方式返回。

原文链接:

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r3-a-raw-pointer-a-t-is-non-owning


觉得本文有帮助?欢迎点赞并分享给更多的人。

更新文章,请关注微信公众号【面向对象思考】

C++核心准则R.3: 原始指针(T*)不应拥有所有权相关推荐

  1. C++核心准则R.2: 只在接口中表示单独对象使用原始指针​

    R.2: In interfaces, use raw pointers to denote individual objects (only) R.2: 只在接口中表示单独对象使用原始指针 Reas ...

  2. C++核心准则R.33: 表达函数会重置widget时,使用unique_ptr(widget)​作参数

    R.33: Take a unique_ptr<widget>& parameter to express that a function reseats the widget R ...

  3. C++核心准则R.32: 通过​unique_ptr(widget)类型参数表示函数试图获取widget的所有权

    R.32: Take a unique_ptr<widget> parameter to express that a function assumes ownership of a wi ...

  4. php 语法 条件变量,C ++核心准则:注意条件变量的陷阱

    今天,我写了一篇关于条件变量的恐怖文章.您应该意识到条件变量的这一问题.C ++核心准则CP 42仅声明:"不要无条件等待". 等待!条件变量支持一个非常简单的概念.一个线程准备一 ...

  5. boost::python模块实现使用原始指针访问数据的示例

    boost::python模块实现使用原始指针访问数据的示例 实现功能 C++实现代码 实现功能 boost::python模块实现使用原始指针访问数据的示例 C++实现代码 #include < ...

  6. modbus软件开发实战指南_C++核心准则?GSL:指南支持库

    GSL: Guidelines support library GSL:指南支持库 The GSL is a small library of facilities designed to suppo ...

  7. 开源压缩算法brotli_Google的Brotli压缩算法,C ++核心准则以及更多新闻

    开源压缩算法brotli 在本周的开源新闻综述中,我们将介绍Google的Brotli压缩算法,适用于GitHub的Classroom,C ++ Core Guidelines等! 2015年9月20 ...

  8. C++ R 原始字符串 R 表示方法,R是原始字符串

    新的C++标准可以在代码里嵌入一段原始字符串,该原始字符串不作任何转义,所见即所得,这个特性对于编写代码时要输入多行字符串,或者含引号的字符串提供了巨大方便. 先介绍特性如下: 原始字符串的开始符号 ...

  9. Rust简短笔记:原始指针(Raw Pointer)

    众所周知,Rust语言的指针是一种安全的指针,它会遵循一定的规则,比如ownership规则,会确保不出现悬挂指针.但是当我们需要写一些底层框架的时候,往往需要绕过这些规则,自由的控制指针,这时候我们 ...

  10. C++核心准则E.25:如果不能抛出异常,模仿RAII方式进行资源管理

    E.25: If you can't throw exceptions, simulate RAII for resource management E.25:如果不能抛出异常,模仿RAII方式进行资 ...

最新文章

  1. [JS][C++]两题斐波那契数列:上台阶、triangle
  2. 什么是CNN?写给小白的机器学习入门贴,Facebook员工打造,47k访问量
  3. 10 个 Linux 中方便的 Bash 别名
  4. 第三章 Java Servlet基础
  5. java编程50实例_java编程实例大全及详解谜底(50例).doc
  6. Codeforces Gym101257F:Islands II(求割点+思维)
  7. P1605 迷宫 dfs回溯法
  8. having vs where
  9. web调试:ie缓存
  10. LaTeX的历史:图灵奖得主1977年开启的计划,引发学术圈重大变革
  11. Linux 平台下 Tomcat 的安装与优化
  12. 基于MSP430f5529的红外循迹小车
  13. 设置div中的背景颜色及div中的字体颜色
  14. fastboot 操作
  15. 1024 程序员节,拿个勋章
  16. 基于java的五子棋游戏的设计_基于Java的五子棋游戏的设计
  17. python单词翻译-python 中英文翻译
  18. 项目管理五大过程与十大知识领域
  19. 有限元非线性问题概述-几何非线性
  20. 基础算法(二):高精度/前缀和与差分

热门文章

  1. 详解:分治算法【Java实现】——汉诺塔问题
  2. 怎么在删除计算机里面搜索记录,Win7如何删除我的电脑搜索栏里面的搜索记录介绍三种删除win7搜索记录的方法...
  3. 2022可用的免费天气预报API接口
  4. 【View基础知识】TouchSlop、VelocityTracker、GestureDetector、Scroller
  5. mysql opened tables_MySQL_MySQL性能优化之Open_Table配置参数的合理配置建议,在MySQL数据库中,Opened_tables表 - phpStudy...
  6. 中小企业的采购现状,如何打破发展艰难的局面?
  7. 什么是云中台系统_什么是云中的超融合?
  8. 厨神之路一--群英荟萃1
  9. 叶俊|从人类基因本能谈到赞美的力量|麻辣总裁幽默SHOW嗨翻全场
  10. 聊点高考往事和驾照科目二考试(r12笔记第86天)