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

1 c++ reference

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

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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

如果我希望函数能够将所有类型的值(变量,从函数返回的临时值,文字等)作为参数,那么对于非对象修改版本(const)和潜在对象修改版本的原型应该是什么?版本(不是const)版本,如果我希望它最有效(避免调用复制构造函数,移动构造函数,赋值运算符,创建临时对象等)?

我不确定应该使用哪种类型的引用。如果这是一个主观的问题,我正在寻找每种方法的利弊。

Sta*_*nny 5

有所有这些用于参数声明的组合都存在的原因。这仅取决于您的需求:

  • void foo(T obj);
    • 呼叫者不想obj被修改[因此已被复制]
    • foo 可以修改 obj [是副本]
    • 如果foo不进行修改,obj仍然优先使用此方法const T&-假设T它很小(适合1-2个CPU寄存器)

  • void foo(const T obj);
    • 呼叫者不想obj被修改[因此已被复制]
    • foo 不能修改 obj
    • 记住,const通常是帮助您发现错误。这就是为什么通常将其用于避免意外修改的原因obj。(例如if (obj = 5)

  • void foo(T& obj);
    • 来电者希望更改为 obj
    • foo 可以修改 obj
    • 引用表示无复制。因此,这对于传递昂贵的复制对象很有用。然而,这可能是小的类型(慢intdouble等等),这意味着一个传递拷贝会更好。

  • void foo(const T& obj);
    • 呼叫者不想obj被修改
    • foo 不能修改 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从此视频制作的流程图图制作了精美的图形:

参数声明流程图