F.21: To return multiple "out" values, prefer returning a struct or tuple(如果需要返回多个输出值,最好返回结构体或者tuple)

Reason(原因)

A return value is self-documenting as an "output-only" value.

Note that C++ does have multiple return values, by convention of using a tuple (including pair),

possibly with the extra convenience of tie at the call site.

Prefer using a named struct where there are semantics to the returned value. Otherwise, a nameless tuple is useful in generic code.

返回值本身就表明了自己是一个只用作输出的值。注意C++是可以同时返回多个值的,通常是使用tuple(包括pair),调用者还可以利用tie获得额外的便利性。如果返回值有特定的含义时使用命名的结构体会更好。否则无名的tuple会更适合一般的代码。

译者注:tie是C++11导入的新特性,可以用于解构tuple元素。具体示例可以参照http://www.cplusplus.com/reference/tuple/tie/

Example(示例)// BAD: output-only parameter documented in a commentint f(const string& input, /*output only*/ string& output_data){// ...output_data = something();return status;}// GOOD: self-documentingtuple f(const string& input){// ...return make_tuple(status, something());}译者注:类似的返回多值的做法在其他语言(例如Python)中已经广泛使用。

C++98's standard library already used this style, because a pair is like a two-element tuple.

For example, given a set my_set, consider:

C++98的标准库中已经使用这种风格,因为pair就像2个元素的tuple。例如,假设有一个set my_set,考虑下面的代码:// C++98result = my_set.insert("Hello");if (result.second) do_something_with(result.first);    // workaround

With C++11 we can write this, putting the results directly in existing local variables:

使用C++11你可以这样写,直接将结果放入已经存在的局部变量。Sometype iter; // default initialize if we haven't alreadySomeothertype success; // used these variables for some other purposetie(iter, success) = my_set.insert("Hello"); // normal return valueif (success) do_something_with(iter);

With C++17 we are able to use "structured bindings" to declare and initialize the multiple variables:

使用C++17,我们可以使用结构化绑定功能定义和初始化多个值:if (auto [ iter, success ] = my_set.insert("Hello"); success) do_something_with(iter);

Exception(例外)

Sometimes, we need to pass an object to a function to manipulate its state.

In such cases, passing the object by reference T& is usually the right technique.

Explicitly passing an in-out parameter back out again as a return value is often not necessary.

For example:

有时我们需要向函数传递一个对象以便控制这个对象的状态。在这种情况下,使用引用T&传递对象通常是正确的方式。一般不需要一方面明确地传递一个输入/输出参数,另一方面却通过返回值输出。例如:istream& operator>>(istream& is, string& s); // much like std::operator>>()for (string s; cin >> s; ) {// do something with line}

译者注:这里说的应该是s。is由于需要支持连续的>>,需要作为返回值返回。

Here, both s and cin are used as in-out parameters.

We pass cin by (non-const) reference to be able to manipulate its state.

We pass s to avoid repeated allocations.

By reusing s (passed by reference), we allocate new memory only when we need to expand s's capacity.

This technique is sometimes called the "caller-allocated out" pattern and is particularly useful for types,

such as string and vector, that needs to do free store allocations.

这里s和cin都用作输入/输出参数。我们通过(非常量)引用传递cin以便控制它的状态。我们传递s以避免重复申请内存。通过重用s(通过引用传递),我们只是在需要扩充s的容量时重新申请内存。这个技术有时被称为“用户申请的输出”模式,这种方式特别适用于类似string和vector那样的类型,它们需要释放申请到的存储空间。

To compare, if we passed out all values as return values, we would something like this:

作为比较,如果我们使用返回值传出所有值,差不多需要这样做:pair get_string(istream& is); // not recommended{string s;is >> s;return {is, s};}for (auto p = get_string(cin); p.first; ) {// do something with p.second}

We consider that significantly less elegant with significantly less performance.

我们认为这种做法明显不够优雅,也不够高效。

For a truly strict reading of this rule (F.21), the exception isn't really an exception because it relies on in-out parameters,

rather than the plain out parameters mentioned in the rule.

However, we prefer to be explicit, rather than subtle.

如果真正严格地理解这条准则(F.21), 这个例外并不是真的例外,因为它依赖于输入/输出参数,而不是本准则提到的简单的输出参数。然而我们强调的是

明确而不是隐含地传递的情况。

Note(注意)

In many cases, it may be useful to return a specific, user-defined type.

For example:

很多情况下,传递一个明确的,用户定义的类型可能是有用的。例如:struct Distance {int value;int unit = 1; // 1 means meters};Distance d1 = measure(obj1); // access d1.value and d1.unitauto d2 = measure(obj2); // access d2.value and d2.unitauto [value, unit] = measure(obj3); // access value and unit; somewhat redundant// to people who know measure()auto [x, y] = measure(obj4);        // don't; it's likely to be confusing

译者注:代码中[x,y]的用法是C++17中引入的结构化绑定(structred binding)

The overly-generic pair and tuple should be used only when the value returned represents independent entities rather than an abstraction.

一般的pair和tuple应该只被用于返回值表现独立实体(数据之间没什么内在联系)的情况,而不是表现某种抽象。

Another example, use a specific type along the lines of variant, rather than using the generic tuple.

另外一个例子,使用和variant类似的特定类型,而不是使用一般的tuple。

译者注:variant是C++17引入的新特性。这个例子可以看做抽象之外的另一种包含明确意义的情况。

Enforcement(实施建议)Output parameters should be replaced by return values.

An output parameter is one that the function writes to, invokes a non-const member function, or passes on as a non-const.

应该使用返回值代替输出参数。输出参数可以是函数写入动作的对象,调用一个非常量成员函数,或者作为一个非常量传递。

.21f## c语言,C++核心准则编译边学-F.21 如果需要返回多个输出值,最好返回结构......相关推荐

  1. 使用说明 vector_C++核心准则编译边学-F.20 输出结果时应该使用返回值

    F.20: For "out" output values, prefer return values to output parameters(输出结果时更应该使用返回值而不是输 ...

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

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

  3. python语言的核心理念是_Python 编程语言的核心是什么?

    01 Python 编程语言的核心是什么? ​ 为什么要问这个问题? 我想要用Python实现WebAssembly,这并不是什么秘密.这不仅可以让Python进入浏览器,而且由于iOS和Androi ...

  4. 关于java的特点不正确的是_关于Java语言的健壮性特点,下列说法不正确的是()。A.Java语言是一种强类型语言,即在编译和运行时...

    关于Java语言的健壮性特点,下列说法不正确的是().A.Java语言是一种强类型语言,即在编译和运行时 更多相关问题 竞争与合作的关系是() A.对立的关系 B.统一的关系 C.既对立又统一的关系 ...

  5. c语言程序既可以编译执行也可以解释执行,2016年山东农业大学信息科学与工程学院C语言程序设计(同等学力加试)复试笔试仿真模拟题...

    一.选择题 1. 计算机高级语言程序的运行方法有编译执行和解释执行两种,以下叙述中正确的是 ( ). A.C 语言程序仅可以编译执行 B.C 语言程序仅可以解释执行 C.C 语言程序既可以编译执行,又 ...

  6. 2.c语言编译预处理,c语言第03章-编译预处理2.ppt

    c语言第03章-编译预处理2 第3章 编译预处理 编译预处理是指,编译时,首先对编译预处理命令进行处理,然后再将预处理后的中间结果进行编译,以得到目标代码. 教学目的: 掌握#define.#incl ...

  7. C 语言编程 — 程序的编译流程

    目录 文章目录 目录 文章目录 C 程序的编译流程 预处理 编译 汇编 链接 编译多个源文件 文章目录 <C 语言编程 - GCC 工具链> <C 语言编程 - 程序的编译流程> ...

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

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

  9. go编译成c语言,Go语言是怎么完成编译的

    Go语言是一门需要编译才能运行的编程语言,也就说代码在运行之前需要通过编译器生成二进制机器码,随后二进制文件才能在目标机器上运行,如果我们想要了解Go语言的实现原理,理解它的编译过程就是一个没有办法绕 ...

  10. cmd编译可以通过执行没有结果_Go语言是如何完成编译的

    Go语言是一门需要编译才能运行的编程语言,也就说代码在运行之前需要通过编译器生成二进制机器码,随后二进制文件才能在目标机器上运行,如果我们想要了解Go语言的实现原理,理解它的编译过程就是一个没有办法绕 ...

最新文章

  1. 用“组策略”修改注册表十大个经典范例
  2. Taurus.MVC 支持Asp.Net Core 的过程
  3. 十进制数和二进制数之间的转换
  4. vs2013缺少Mvc 怎么办?
  5. AI降成本利器!阿里云弹性加速计算实例来了,最高节省50%推理成本
  6. mysql主从复制实践之单数据库多实例
  7. theoretical-零基础学Qt4编程之Qt核心机制与原理之信号与槽-
  8. map java 用法_java中map 9种常规用法
  9. DevOps团队如何选择监控工具
  10. 网易公开课专辑下载脚本python
  11. VirtualBox 安装ghost xp(雨林木风)
  12. Android仿微信朋友圈发动态功能(相册图片多选)
  13. android安卓-子线程计时器TimeCountThread-时分秒-实用功能系列
  14. Axure统计图表设计(Excel设计统计图表、HighChart设计统计图表)
  15. 算法设计——基姆拉尔森计算公式:计算几月几号是星期几
  16. Android studio打包之 BuildVariants
  17. 交互设计指南 iphone_交互设计:角色创建指南
  18. 谷歌浏览器与驱动下载,以及放置位置
  19. 案例 :深度学习 V.S. 谜题游戏
  20. mysql leng() 与 char_length() 的区别,注意一下。

热门文章

  1. WAP开发环境的设置[IIS, APACHE, HTTPD]
  2. 接收流信息---字符串
  3. 应用SqlParameter防止注入式攻击,打开主窗体关闭登录窗体
  4. 20190911每日一句
  5. 一级指针易犯错误模型
  6. Atitit 高等教育 中产教育 普通教育的异同 目录 1. 顶层精英教育 1 1.1. 领导力 影响力 1 1.2. 国王规范 1 1.3. 宗教领袖 1 1.4. 决策能力 1 1.5. 国际视
  7. Atitit everthing placeholder index list 目录 1.1. sumdoc 2019 zipver t1---t91 1 1.2. 00 sumdoc ever
  8. Atitit 编程语言的类型系统 目录 1.2. 动态类型语言(Dynamically Typed Language): 1 1.3. 静态类型语言(Statically Typed Languag
  9. Atitit 文件远程传输读写协议 scp http ftp nfs webdav smb D:\Program Files\Git\usr\bin\scp.exe 4.密码安全策略不完善 在
  10. Atitit.故障排除系列---NoClassDefFoundError NoClassDefFoundError