c++ - 作为 const 和通过引用传递 - 值得吗?

标签 c++

这个问题在这里已经有了答案:




10年前关闭。




Possible Duplicate:
How to pass objects to functions in C++?



在我的游戏中,我过度使用数学 vector 和运算符重载它们。
class Vector
{
   float x, y;
};

这基本上是关于我的 Vector 类(不包括方法)。

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

那么,下面的代码示例中的性能差异在哪里?
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;
}
  • 我应该使用这三个中的哪一个,为什么?
  • 每个选项对编译器的优化过程有什么好处?
  • 何时何地我必须特别小心?
  • 最佳答案

    路过 const引用是传递对象的首选方式,作为按值传递的智能替代方法。当你路过时const引用,您通过引用获取参数(避免制作它的任何拷贝),但不能对原始对象进行任何更改(就像按值获取参数时会发生的情况一样)。

    如果考虑这三个函数:

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

    所有这些之间都有细微的区别。例如,第一个函数将在您传入 Vector 时调用复制构造函数。以便它拥有自己的 Vector 的本地拷贝.如果您的复制构造函数需要一段时间运行或进行大量资源分配和释放,这可能会很慢,但您可以对参数进行任何您想要的更改,而不会冒任何更改传播回调用者的风险。随着参数被清除,函数末尾还会有一个析构函数调用,如果这个代价太大,最好避免这种设置。也就是说,对于小物体,它可能是完全可以接受的。

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

    此函数的最终版本采用 Vector来自 const引用,就像通过常规引用传递一样,避免了任何复制。但是,当服用Vector来自 const引用,您不得对 Vector 进行任何更改在函数内部,所以客户可以假设 Vector不会被修改。 (是的,从技术上讲,如果它写得不好或具有 mutable 数据成员,则可以对其进行修改,但我们现在将忽略它。这是此处重要的高级思想)。如果您希望能够检查函数中的值而不复制它并且不改变它,那么这个选项会很好。

    pass-by-reference 和 pass-by- const 之间还有一个区别-reference,这就是函数在右值上的行为。如果您有临时的 Vector对象 - 或者您通过编写 Vector() 显式创建它或者对它进行一些数学运算,比如写 v1 + v2 - 那么你不能通过那个临时Vector进入一个通过引用获取其参数的函数,因为引用只能绑定(bind)到左值。这个想法是,如果你有这样的功能:
    void DoSomething(Vector& v) {
         v.x = 0.0f;
    }
    

    那么写就没意义了
    DoSomething(v1 + v2);
    

    因为这会改变 x临时表达式的字段。为了防止这种情况,编译器将拒绝编译此代码。

    但是,C++ 有一个异常(exception),它允许您将右值传递到以 const 为参数的函数中。引用,因为从直觉上讲,您不应该通过 const 修改对象。引用。因此这段代码是完全合法的:
    void DoSomething(const Vector& v) {
        cout << v.x << endl;
    }
    
    DoSomething(v1 + v2);
    

    所以,总结一下——
  • 传值和传值const -reference 暗示类似的事情 - 您希望能够查看该值而不能修改它。
  • 任何时候你可以使用 pass-by-value 你可以改用 pass-by- const - 引用而不影响程序的正确性。但是,在引用的间接性与复制和破坏参数的成本之间存在性能权衡。
  • 路过非const -reference 应该用于表示“我想修改参数”。
  • 您不能将右值传递给采用非 const 参数的函数。引用。

  • 希望这可以帮助!

    关于c++ - 作为 const 和通过引用传递 - 值得吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5060137/

    相关文章:

    c++ - 从 ActiveX 控件中的方法返回值

    c++ - 如何定义在两个类之外的模板类内部的非模板类中声明的友元函数?

    c++ - 什么时候应该使用 lua 脚本,什么时候不应该

    c++ - 函数的默认值作为函数参数

    c++ - 为什么我得到这个输出?

    c++ - 以 double 的形式改变一位

    c++ - 为什么我的 cout 语句没有打印一半?

    c++ - 标签分派(dispatch)结构不能插入对象类型

    c++ - 如何从阻力网络中去除循环

    c++ - LNK2005,C++/CLI,不知道