是否使用对象的指针和引用作为函数参数更轻
Is using pointers and references of an object as function arguments lighter?
我想知道是否:
//Let's say T is a big class with + operand implemented.
T add(T* one, T* two)
{
return *one + *two;
}
和:
T add(T& one, T& two)
{
return one + two;
}
比这轻:
T add (T one, T two)
{
return one +two;
}
如果不是,那么如果没有任何东西会改变对象的数据,为什么有人会使用指针或对对象的引用而不是对象本身作为函数的参数?
对于光类型,即适合寄存器的光源类型,例如 int
,这没有区别,因为它们就像指向它们的指针一样容易复制。实际上,额外的间接寻址可能会损害性能,这就是为什么在不需要时应避免引入它的原因。
但是,所使用的类型复制成本可能很高。每天的例子是std::string
。引用避免复制,并且在函数需要"重"对象的地方受到青睐。
在函数模板中,在采用各种对象类型时通常应使用引用,除非您确定唯一涉及的类型是"轻量级",例如迭代器或标量。
不过,这条规则也有不太明显的例外。考虑std::accumulate
:
template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );
在这里,init
是按价值获取的。原因很简单:在通常的实现中,init
被修改,因为它直接在计算中使用 - 没有引入中间对象。
template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = init + *first; // Here
}
return init;
}
指针本身不应用于间接函数参数。它们在 C 中使用,其中不存在引用。
使用基元类型时,按指针或引用传递它并不比按值传递轻。但如果它是一个大对象,则按指针或引用传递将比按值传递轻,因为复制大对象的开销。
如果"更轻"的意思是"更有效率",答案(对于整数)是否定的——唯一一次通过指针或引用传递参数可能比按值传递更有效,如果你传递的对象非常大(例如 sizeof(theObjectType) 明显大于指针的典型大小的 4 或 8 个字节), 或者,如果对象的类具有复制构造函数,其实现在计算上是昂贵的。 请注意,当通过指针或引用传递时,CPU 在访问数据时必须取消引用指针/引用,这并非完全免费。
如果不是,那么为什么有人会使用指针或对对象的引用 而不是对象本身作为函数的参数,如果没有的话 会改变对象的数据吗?
可能是他们想要向函数传达对象的特定实例,而不是(仅)对象的内容。 例如,可以(尽管做法不好)编写一个函数,如果您传入指向特定全局对象的指针,该函数的行为与在任何其他指针中传递时的行为不同。
通过指针传递还为调用方提供了将 NULL 作为参数传入的选项,如果您希望调用方能够指定"未为此参数提供任何值",这将非常有用。
:视情况而定。
如果您想知道复制或通过引用传递是否更便宜,或者正确的事情,请考虑以下事项:
与指向对象的指针相比,复制对象的成本有多高。
无论如何,根据参数的传递方式,有时可以省略副本。对于
int
,指针/引用充其量不会更昂贵。- 请记住,减少混叠有好处。
请记住,你总是可以无情地掠夺按值传递的参数,就像通过右值引用传递的参数一样。
对其他人来说并非如此。并不是说这些考虑对
int
或其他类型不管理更昂贵的资源有影响。- 完全省略论点有意义吗?
在这种情况下,您必须通过指针传递,或使用类似 未来std::optional
.
如果不是,指针在语义上是错误的选择。
无论如何,永远不要传递非const
指针或引用,除非它应该由函数修改。
此外,如果您认真对待性能,请始终进行衡量。
请记住,大部分时间只花在代码的一小部分上。
不,您的最后一个版本是"更轻"。
但这是因为int
参数可以很容易地在堆栈上传递。对于较大的数据类型、类等,传递指针更有效。
此外,如果您需要更改函数中某个参数的值,则需要一个指向它的指针(其中的引用是一种类型)才能修改它。
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数