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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++核心准则边译边学-F.16 对于输入参数来说,拷贝代价小的传值,其他传递const参照相关的知识,希望对你有一定的参考价值。


F.16: For "in" parameters, pass cheaply-copied types by value and others by reference to ​​const(对于输入参数来说,拷贝代价小的传值,其他传递const参照)​

Reason(原因)

Both let the caller know that a function will not modify the argument, and both allow initialization by rvalues.

两种方式都可以让调用者知道函数不会修改参数并且都可以通过右值初始化。

What is "cheap to copy" depends on the machine architecture, but two or three words (doubles, pointers, references) are usually best passed by value. When copying is cheap, nothing beats the simplicity and safety of copying, and for small objects (up to two or three words) it is also faster than passing by reference because it does not require an extra indirection to access from the function.

什么是“拷贝代价小”和机器架构有关,但是2到3个字(双精度数,指针,引用)通常最适合传值。如果拷贝代价小,没有方法可以超过拷贝的简单和安全,另外,对于小对象(不超过2到3个字)来说,由于函数不需要额外间接访问,因此传值会比传址的速度更快。

Example(示例)

 

void f1(const string& s);  // OK: pass by reference to const; always cheap
void f2(string s); // bad: potentially expensive
void f3(int x); // OK: Unbeatable
void f4(const int& x); // bad: overhead on access in f4()

For advanced uses (only), where you really need to optimize for rvalues passed to "input-only" parameters:

(只)对于高级的用法,需要优化为向输入参数传递右值引用的情况有:

  • If the function is going to unconditionally move from the argument, take it by ​​&&​​. See F.18.
    如果函数会无条件的移动参数的内容,使用&&。参考F.18
  • If the function is going to keep a copy of the argument, in addition to passing by ​​const&​​ (for lvalues), add an overload that passes the parameter by ​​&&​​ (for rvalues) and in the body ​​std::move​​s it to its destination. Essentially this overloads a "will-move-from"; see F.18.
    如果函数会管理一个参数的拷贝,除了使用功能const&(对于左值)以外,增加一个使用&&(对于右值)传递参数的重载函数并且在内部使用std::move移动参数内容到目标上。本质上这个重载是一个“将要移动形式”;参考F.18
  • In special cases, such as multiple "input + copy" parameters, consider using perfect forwarding. See F.19.
    对于
  • 特殊场合,例如多重“输入+拷贝”参数,考虑使用完美的forward。参考F.19

 

译者注:关于forward,请参考作者的以下文章:

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


Example(示例)

 

int multiply(int, int); // just input ints, pass by value
// suffix is input-only but not as cheap as an int, pass by const&
string& concatenate(string&, const string& suffix);
void sink(unique_ptr<widget>); // input only, and moves ownership of the widget

Avoid "esoteric techniques" such as:

避免使用“只有高手才懂的技术”,例如:

  • Passing arguments as ​​T&&​​ "for efficiency". Most rumors about performance advantages from passing by ​​&&​​ are false or brittle (but see F.18 and F.19).
    为了提高效率而使用T&&。许多通过传递&&获得性能优势的传言都是假的或者脆弱的。(但是请参照F.18和F.19)
  • Returning ​​const T&​​ from assignments and similar operations (see F.47.)
    通过复制或者类似操作返回const T&(参考F.47)

Example(示例)

Assuming that ​​Matrix​​​ has move operations (possibly by keeping its elements in a ​​std::vector​​):

假设Matrix实现了移动操作(例如使用std::vector保管元素)

 

Matrix operator+(const Matrix& a, const Matrix& b)

Matrix res;
// ... fill res with the sum ...
return res;

Matrix x = m1 + m2; // move constructor
y = m3 + m3; // move assignment

 

Notes(注意)

The return value optimization doesnt handle the assignment case, but the move assignment does.

返回值优化不会处理赋值的情况,但是移动赋值会。

 

译者注:

1.返回值优化(RVO)已经足够好,不要在寻求更高级的技术了。

2.移动构造函数和移动赋值请参照作者文章:

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

 

A reference may be assumed to refer to a valid object (language rule). There is no (legitimate) "null reference." If you need the notion of an optional value, use a pointer, ​​std::optional​​, or a special value used to denote "no value."

可以假设引用参照的是有效对象(语言准则)。不存在(合理的)“空引用”。如果需要可选值概念,使用指针,std::optional或者特殊值表示“没有值”。

 

Enforcement(实施建议)

  • (Simple) ((Foundation)) Warn when a parameter being passed by value has a size greater than ​​2 * sizeof(void*)​​. Suggest using a reference to ​​const​​ instead.
    (简单)((基本准则)) 当传值的大小超过2*sizeof(void*)时,报警。建议使用const引用。
  • (Simple) ((Foundation)) Warn when a parameter passed by reference to ​​const​​ has a size less than ​​2 * sizeof(void*)​​. Suggest passing by value instead.
    (简单)((基本准则))当小于2*sizeof(void*)的参数使用const传址时,报警。
  • (Simple) ((Foundation)) Warn when a parameter passed by reference to ​​const​​ is ​​move​​d.
    (简单)((基本准则))当使用const传址的参数的内容被移动时,报警。

 

觉得本文有帮助,欢迎点赞并分享给更多的朋友!

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

以上是关于C++核心准则边译边学-F.16 对于输入参数来说,拷贝代价小的传值,其他传递const参照的主要内容,如果未能解决你的问题,请参考以下文章

C++核心准则边译边学-文档结构

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

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

c++的核心准则

c++的核心准则

Gopher 学个函数边学边练,简单为 Go 上个分