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

标签 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);

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

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

其他方法通过引用获取对象(前两种通过左值引用,后两种作为右值引用)应该省略任何复制。 const 限定版本 promise 不修改引用的对象。

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

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

最佳答案

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

  • 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 , 这使得它很少有用
    • 但是,这不允许将左值作为参数传递。

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


一些额外的位:

  • copy-swap-idiom
  • (const T& obj)通常比 (T obj) 更糟糕出于很多原因。但记住来电者总是可以让T只是 std::reference_wrapper<const T> 以避免复制。不过,这可能会破坏该功能。
  • 即使你不这样做 std::move 有很多进展正在进行 - 假设该类型具有必要的运算符。
  • 函数/Lambda?按值传递:template <typename F> void execute(F f) { f(); }

最后值得分享的是Bisqwit制作的这张流程图来自 this video这是一个漂亮的图形:

parameter declaration flow chart

关于c++ - 在现代 C++ 中获取参数的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56869094/

相关文章:

c++ - 错误 C2668 : 'boost::bind' : ambiguous call to overloaded function

JavaScript 对象引用

c# - AutoMapper,如何保持映射对象之间的引用?

python - 添加到列表中的对象最终会添加到所有列表对象

c++ - 从 C++ vector 中提取引用

c++ - 如何减少内核中分支/if 语句的数量?

c++ - 具有恒定时间复杂度的无向图边的数据结构

c++ - 在不为数组分配内存的情况下工作

c++ - 具有返回值的信号/插槽不起作用

.net - 如何告诉 Visual Studio 自动加载某些引用?