0
点赞
收藏
分享

微信扫一扫

C++核心准则边译边学-F.20 输出结果时更应该使用返回值而不是输出参数


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

Reason(原因)

A return value is self-documenting, whereas a ​​&​​ could be either in-out or out-only and is liable to be misused.

返回值本身可以说明用途,而引用类型可以是输入/输出参数也有可能只是输出参数,容易被误用。

This includes large objects like standard containers that use implicit move operations for performance and to avoid explicit memory management.

这种观点可以覆盖像标准容器那样的大对象,它们会为了性能和避免显式内存管理而使用隐式移动操作。

If you have multiple values to return, use a tuple or similar multi-member type.

如果你有多个值需要返回,使用tuple或者类似的多成员类型。

 

译者注:tuple可以参考以下文章。

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

Example(示例)

 

// OK: return pointers to elements with the value xvector<const int*> find_all(const vector<int>&, int x);
// Bad: place pointers to elements with value x in-outvoid find_all(const vector<int>&, vector<const int*>& out, int x);

Note(注意)

A ​​struct​​ of many (individually cheap-to-move) elements may be in aggregate expensive to move.

包含多个(单独看都可以低成本移动)元素的结构体合起来移动时可能会代价高昂。

It is not recommended to return a ​​const​​ value. Such older advice is now obsolete; it does not add value, and it interferes with move semantics.

不推荐返回常量值。这种过时的建议现在已经被淘汰;它不会带来好处,而且其接口含有移动语义。

 

const vector<int> fct();    // bad: that "const" is more trouble than it is worth
vector<int> g(const vector<int>& vx){ // ... fct() = vx; // prevented by the "const" // ... return fct(); // expensive copy: move semantics suppressed by the "const"}

The argument for adding ​​const​​ to a return value is that it prevents (very rare) accidental access to a temporary. The argument against is prevents (very frequent) use of move semantics.

建议为返回值增加const修饰的观点认为,这样会阻止(极少发生的)对临时变量的意外访问。相反的观点认为这样做会(非常多地)阻止移动语义的运用。

Exceptions(例外)

  • For non-value types, such as types in an inheritance hierarchy, return the object by​​unique_ptr​​ or ​​shared_ptr​​.
    对于非值类型函数,例如处于继承关系中的类型,通过unique_ptr或者shared_ptr返回对象。
    译者注:两种方式都可以避免不必要的拷贝动作。
  • If a type is expensive to move (e.g.,​​array<BigPOD>​​), consider allocating it on the free store and return a handle (e.g., ​​unique_ptr​​), or passing it in a reference to non-​​const​​ target object to fill (to be used as an out-parameter).
    如果某种类型(例如array<BigPOD>)的移动成本很高,考虑从自由存储上为其申请内存并使用句柄(例如unique_prt)返回它,或者通过用于填充的非常量对象的引用来传递。
    译者注:POD是Plain old data structure的简称,是C++语言的标准中定义的一类数据结构,可以简单地理解只包含单纯数据类型的结构体。
  • To reuse an object that carries capacity (e.g.,​​std::string​​, ​​std::vector​​) across multiple calls to the function in an inner loop: treat it as an in/out parameter and pass by reference.
    为了让处于内循环中的函数调用可以重复使用带有容量的对象(例如std::string,std::vector):把它看做输入/输出参数并通过引用传递。

Example(示例)

 

struct Package {      // exceptional case: expensive-to-move object    char header[16];    char load[2024 - 16];};
Package fill(); // Bad: large return valuevoid fill(Package&); // OK
int val(); // OKvoid val(int&); // Bad: Is val reading its argument

译者注:示例代码说明的是POD使用引用传递输出值,而小数据者应该直接使用返回值。

 

Enforcement(实施建议)

  • Flag reference to non-​​const​​ parameters that are not read before being written to and are a type that could be cheaply returned; they should be "out" return values.
    警告那些没有在写之前读(没有输入用途)而且可以低成本返回的参数,它们应该作为返回值输出。
  • Flag returning a​​const​​ value. To fix: Remove ​​const​​ to return a non-​​const​​ value instead.
    警告返回常数值的状况。修改方法:去掉常量修饰,返回一个非常量。

 


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

 

举报

相关推荐

0 条评论