可以通过多种不同的方式获取参数:
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
- 引用意味着没有复制。所以这对于传递昂贵的复制对象很有用。但是,这对于小类型(
int
、double
等)来说可能会很慢,这意味着传递复制会更好。
- 来电者希望更改为
-
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这是一个漂亮的图形:
关于c++ - 在现代 C++ 中获取参数的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56869094/