温馨提示:本文翻译自stackoverflow.com,查看原文请点击:reference - Most efficient way to take parameters in modern C++?
c++ reference

reference - 在现代C ++中获取参数的最有效方法?

发布于 2020-03-27 11:28:33

可以采用许多不同的方式获取参数:

void foo(T obj);
void foo(const T obj);
void foo(T& obj);
void foo(const T& obj);
void foo(T&& obj);
void foo(const T&& obj);

我不包括通过指针获取参数,因为指针可能已经是类型了T

前两种方式是按值获取对象,这将导致对象被复制(如果没有通过智能编译器进行优化)。

其他方式是通过引用获取对象(前两个通过l值引用,后两个作为r值引用),该对象应省略复制。const合格版本承诺不修改引用的对象。

If I want my function to be able to take as parameters all kinds of values (variables, temporaries returned from functions, literals etc.) what should be its prototype for a not-object-modifying version (const) and a potentially-object-modifying version (not const) version, if I want it to be the most efficent (avoid invoking copy constructors, move constructors, assignment operators, creating temporaries etc.)?

I'm not sure which type of references should I use. If this is a subjective question I am looking for pros and cons of each approach.

查看更多

查看更多

提问者
user11313931
被浏览
13
Stack Danny 2019-07-03 21:20

There is a reason why all these combinations for parameter declaration exist. It just depends on what you need:

  • void foo(T obj);
    • the caller doesn't want obj to be modified [so it's copied]
    • foo can modify obj [it's a copy]
    • if foo doesn't modify obj this is still prefered over const T& - assuming T is small (fits 1-2 CPU registers)

  • void foo(const T obj);
    • the caller doesn't want obj to be modified [so it's copied]
    • foo can't modify obj
    • remember, const is often to help you find errors. That's why this is generally used to avoid accidentely modifying obj. (e.g. if (obj = 5))

  • void foo(T& obj);
    • the caller expects a change to obj
    • foo can modify obj
    • a reference means no copying. So this is useful for passing expensive-to-copy objects. However, this could be slow for small types (int, double etc.) meaning a pass-by-copy would be better.

  • void foo(const T& obj);
    • the caller doesn't want obj to be modified
    • foo can't modify obj
    • 引用表示无复制。由于它是不可修改的,因此这是参数化大型只读容器的理想方法。因此:对于昂贵的复制对象而言非常便宜,对于小型类型而言可能会很慢。

  • void foo(T&& obj);
    • 呼叫者不在乎会发生什么,obj如果之后为空,则不会有任何问题
    • foo 可以 obj通过将信息移到另一个地方来窃取数据来进行修改

  • void foo(const T&& obj);
    • foo 不能修改 obj,这使得它很少有用
    • 但是,这不允许将左值作为参数传递。

有很多特殊情况,所以这不是完整的列表。


一些额外的位:

  • 复制交换习语
  • (const T& obj)通常(T obj)由于许多原因而不仅仅是糟糕但是请记住,呼叫者总是可以T简单std::reference_wrapper<const T>地避免复制。但是,这可能会破坏功能。
  • 即使您没有std::move也要进行很多操作-假设类型具有必要的运算符。
  • 函数/ Lambdas?按值传递:template <typename F> void execute(F f) { f(); }

最后,值得分享的是Bisqwit从此视频中制作的流程图流程图可以制作出精美的图形:

参数声明流程图