可以采用许多不同的方式获取参数:
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.
There is a reason why all these combinations for parameter declaration exist. It just depends on what you need:
void foo(T obj);
obj
to be modified [so it's copied]foo
can modify obj
[it's a copy]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);
obj
to be modified [so it's copied]foo
can't modify obj
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);
obj
foo
can modify obj
int
, double
etc.) meaning a pass-by-copy would be better.void foo(const T& obj);
obj
to be modifiedfoo
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
,也要进行很多操作-假设类型具有必要的运算符。template <typename F> void execute(F f) { f(); }