作为const并通过引用传递-值得吗? [英] Passing as const and by reference - Worth it?

查看:92
本文介绍了作为const并通过引用传递-值得吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

在我的游戏中,我过度使用数学向量和运算符对它们的重载。

In my game I make excessive use of mathematical vectors and operator overloading of them.

class Vector
{
   float x, y;
};

这基本上是关于我的Vector类的(方法除外)。

That's basically all about my Vector class (methods excluded).

我不是C ++专家,我已经看过并阅读了有关以const传递和通过引用传递的信息。

I am not an expert in C++ and I've seen and read about passing as const and passing by reference.

那么,性能在哪里?以下代码示例中的差异?

So, where are the performance differences in the below code example?

Float RandomCalculation( Vector a, Vector b )
{
    return a.x * b.x / b.x - a.x * RANDOM_CONSTANT;
}

// versus..

Float RandomCalculation( Vector& a, Vector& b )
{
    return a.x * b.x / b.x - a.x * RANDOM_CONSTANT;
}

// versus..

Float RandomCalculation( const Vector& a, const Vector& b )
{
    return a.x * b.x / b.x - a.x * RANDOM_CONSTANT;
}




  • 我应该使用三个,并且为什么?

  • 每个选项对编译器的优化过程都有哪些优势?

    • Which of the three should I use, and why?
    • What advantages for the optimization process of the compiler does each of the options have?

      我在何时何地必须特别小心?

      When and where do I have to be especially careful?

      推荐答案

      const 引用是传递对象的首选方法,它是值传递的明智选择。当您通过 const 引用传递时,您可以通过引用接受该参数(避免对其进行任何复制),但是无法对原始对象进行任何更改(可能会发生很多情况)

      Passing by const reference is the preferred way to pass around objects as a smart alternative to pass-by-value. When you pass by const reference, you take the argument in by reference (avoiding making any copies of it), but cannot make any changes to the original object (much as would happen when you would take the parameters in by value).

      如果考虑以下三个函数:

      If you consider these three functions:

      void VersionOne(Vector v);
      void VersionTwo(Vector& v);
      void VersionThree(const Vector& v);
      

      它们之间有细微的区别。例如,当您传入 Vector 时,第一个函数将调用复制构造函数,以使其具有自己的 Vector 的本地副本。 code>。如果您的副本构造函数需要一段时间才能运行,或者需要大量的资源分配和释放,那么这可能会很慢,但是您可以对参数进行任何更改,而不会冒任何更改传播到调用方的风险。在清理完参数后,函数的末尾还将有一个析构函数调用,如果代价太大,建议避免这种设置。也就是说,对于小型物体,这可能是完全可以接受的。

      There are subtle distinctions between all of them. The first function, for example, will invoke the copy constructor when you pass in a Vector so that it has its own local copy of the Vector. If your copy constructor takes a while to run or does a lot of resource allocation and deallocation, this may be slow, but you can make any changes you want to the parameter without risking any changes propagating back up to the caller. There will also be a destructor call at the end of the function as the argument is cleaned up, and if this is too large a cost it may be advisable to avoid this setup. That said, for small objects it may be perfectly acceptable.

      此函数的第二个版本采用了 Vector 通过引用,这意味着该函数可以对 Vector 进行所需的任何更改,并且这些更改将传播回调用者。每当您看到一个通过非 const 引用接受参数的函数时,例如 VersionTwo 函数,您应该假定它将修改参数,因为如果不进行任何修改,它将由 const 引用采用。如果您需要对 Vector 进行更改,则很有可能通过引用获取该值;例如,通过旋转,缩放等。这里涉及的一个折衷是 Vector 在传递给此函数时不会被复制,因此您将避免调用复制构造函数和析构函数。这可能会对您的程序产生性能影响,不过,如果您出于这种原因,则应该通过 const 参考传递。需要注意的一件事是,遵循引用与遵循指针非常相似(实际上,大多数引用实现只是将它们视为已自动取消引用的指针对待),因此,每次访问该指针时,性能都会受到影响。数据通过参考。不过,只有分析可以告诉您这是否是一个主要问题,除非您有特定的理由认为它有问题,否则我不会担心。

      The second version of this function takes in a Vector by reference, which means that the function can make any changes it wants to the Vector and the changes will propagate back up to the caller. Whenever you see a function that takes an argument by non-const reference, like this VersionTwo function, you should assume that it will be modifying the argument, since if it weren't going to make any modifications, it would be taken by const reference. You will most likely take in the value by reference if you need to make changes to the Vector; for example, by rotating it, scaling it, etc. One tradeoff involved here is that the Vector will not be copied when it is passed into this function, and so you will avoid a call to the copy constructor and destructor. This may have performance implications for your program, though if that's your reasoning you should probably go with pass by const reference. One thing to note is that following a reference is very similar to following a pointer (in fact, most implementations of references just treat them as though they were automatically-dereferenced pointers), so there may be a small performance hit every time you access the data through the reference. Only profiling can tell you whether or not this is a major problem, though, and I wouldn't worry about it unless you had a specific reason to think it was at fault.

      此函数的最终版本采用 const 引用的 Vector ,就像通过常规引用传递一样,避免任何复制。但是,当采用 const Vector 引用时,禁止对 Vector ,因此客户可以假定 Vector 不会被修改。 (是的,从技术上讲,如果编写不佳或具有 mutable 数据成员,则可以对其进行修改,但我们暂时将其忽略。重要的是高层概念这里)。如果您希望能够检查函数中的值而无需复制它且不对其进行突变,则此选项将是不错的选择。

      The final version of this function takes in a Vector by const reference, which, like passing by regular reference, avoids any copying. However, when taking the Vector by const reference, you are prohibited from making any changes to the Vector inside the function, so clients can assume that the Vector will not be modified. (Yes, technically it could be modified if it is poorly-written or has mutable data members, but we'll ignore that for now. It's the high-level idea that's important here). This option would be good if you wanted to be able to inspect the value in the function without copying it and without mutating it.

      传递之间还有一个不同之处-reference和pass-by- const -reference,这就是该函数在rvalues上的行为。如果您有一个临时的 Vector 对象,则可以通过编写 Vector()或进行一些数学运算来显式地创建它就像编写 v1 + v2 一样-然后您不能将该临时 Vector 传递给通过引用获取其参数的函数因为引用只能绑定到左值。这个想法是,如果您具有这样的功能:

      There is one more difference between pass-by-reference and pass-by-const-reference, and that's the behavior of the function on rvalues. If you have a temporary Vector object - either you created it explicitly by writing Vector() or by doing some mathematical operation on it like writing v1 + v2 - then you cannot pass that temporary Vector into a function that takes its parameter by reference because references can only bind to lvalues. The idea is that if you have a function like this:

      void DoSomething(Vector& v) {
           v.x = 0.0f;
      }
      

      然后写没有任何意义

      DoSomething(v1 + v2);
      

      因为这将更改 x 字段临时表达。为了防止这种情况,编译器将拒绝编译该代码。

      Since this would be changing the x field of a temporary expression. To prevent this, the compiler will refuse to compile this code.

      但是,C ++会产生一个异常,并允许您将右值传递给使用<$ c $作为参数的函数c> const 引用,因为从直观上讲,您不应该能够通过 const 引用来修改对象。因此,此代码是完全合法的:

      However, C++ makes an exception and lets you pass rvalues into functions that take their argument by const reference, because, intuitively, you shouldn't be able to modify an object through a const reference. Thus this code is perfectly legal:

      void DoSomething(const Vector& v) {
          cout << v.x << endl;
      }
      
      DoSomething(v1 + v2);
      

      所以,总结一下-


      1. 传递值和传递 const -引用表示类似的事情-您希望能够查看值而又不能

      2. 每次使用传递值时,都可以使用传递 const -引用而不影响程序的正确性。但是,在引用的间接引用与复制和销毁参数的成本之间存在性能折衷。

      3. Pass-by-non- const -reference应该用来表示我想修改参数。

      4. 不能将rvalue传递给使用非 const接受参数的函数参考。

      1. Pass-by-value and pass-by-const-reference imply similar things - you want to be able to look at the value without being able to modify it.
      2. Any time you could use pass-by-value you could instead use pass-by-const-reference without affecting the correctness of the program. However, there are performance tradeoffs between the indirection of the reference and the cost of copying and destructing the parameter.
      3. Pass-by-non-const-reference should be used to indicate "I want to modify the argument."
      4. You cannot pass rvalues into functions that take their arguments by non-const reference.

      希望这会有所帮助!

      这篇关于作为const并通过引用传递-值得吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆