使用对象的指针和引用作为函数参数是否更轻松?

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;
}

如果不是,那么如果没有任何东西会改变对象的数据,为什么有人会使用指向对象的指针或引用而不是对象本身作为函数的参数?

不,您的最新版本是 "lighter"。

但那是因为 int 参数可以很容易地在堆栈上传递。对于更大的数据类型,类 等,传递指针更有效。

此外,如果您需要更改函数内某个参数的值,则需要一个指向它的指针(引用是一种类型)才能修改它。

如果 "lighter" 你的意思是 "more efficient",答案(对于整数)是否定的——唯一一次通过指针或引用传递参数可能比通过值传递更有效是如果您传递的对象非常大(例如 sizeof(theObjectType) 明显大于指针的典型大小的 4 或 8 字节),或者如果对象的 class 具有复制构造函数,其实现是计算性的昂贵的。请注意,当通过指针或引用传递时,CPU 必须在访问数据时取消引用 pointer/reference,这并非完全免费。

If not, then why would someone use pointers or references to an object instead of the objects themselves as function's arguments if nothing will change the object's data?

可能是他们想向函数传递对象的特定实例而不是(仅)对象的内容。例如,如果您传入一个指向特定全局对象的指针,则可以编写一个行为与传入任何其他指针时行为不同的函数(尽管是不好的做法)。

通过指针传递还为调用者提供了将 NULL 作为参数传递的选项,如果您希望调用者能够指定 "no value has been provided for this argument".

,这将很有用

对于光类型,即那些适合寄存器的类型,例如 int,它没有什么区别,因为它们就像指向它们的指针一样容易复制。实际上,额外的间接寻址可能反而会损害性能,这就是为什么在不需要时应避免引入它的原因。
但是,所使用的类型的复制成本可能很高。每天的例子是 std::string。引用避免了复制,并且在函数需要 "heavy" 个对象的地方受到青睐。

在函数模板中,当采用各种对象类型时,通常应该使用引用,除非您确定所涉及的唯一类型是 "light",例如迭代器或标量.
不过,这条规则也有不太明显的例外。考虑 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 中使用,其中引用不存在。

答案通常是:视情况而定。

如果您想知道复制或通过引用传递是否更便宜或正确,请考虑这些:

  1. 与指向对象的指针相比,复制对象的开销有多大。
    无论如何,根据参数的传递方式,有时可以省略副本。

    对于int,pointer/reference最多也不会贵。

  2. 记住减少锯齿是有好处的。
  3. 记住,你总是可以无情地掠夺按值传递的参数,就像那些按右值引用传递的参数一样。
    其他人则不然。

    并不是说这些考虑因素对 int 或其他不管理更昂贵资源的类型有影响。

  4. 完全省略参数有意义吗?
    在那种情况下,你必须通过指针传递,或者使用类似未来的东西 std::optional.
    如果不是,指针是语义错误的选择。

无论如何,永远不要传递非const指针或引用,除非它应该被函数修改。

此外,如果您非常重视性能,总是衡量
请记住,大部分时间只花在一小部分代码上。

当使用基本类型时,通过指针或引用传递它并不比通过值传递更轻便。但如果是大对象,指针传递或引用传递会比值传递轻,因为复制大对象的开销。