【问题标题】:What is the use of passing const references to primitive types?将 const 引用传递给原始类型有什么用?
【发布时间】:2010-10-14 22:26:18
【问题描述】:

在我维护的一个项目中,我看到很多这样的代码,用于简单的get/set 方法

const int & MyClass::getFoo() { return m_foo; }

void MyClass::setFoo(const int & foo) { m_foo = foo; }

这样做的意义何在?

int MyClass::getFoo() { return m_foo; }  // Removed 'const' and '&' 

void MyClass::setFoo(const int foo) { m_foo = foo; }  // Removed '&'

传递对原始类型的引用应该需要与传递类型的值本身相同(或更多)的工作,对吧?
毕竟只是一个数字...
这只是一些尝试的微优化还是有真正的好处?

【问题讨论】:

    标签: c++ reference constants primitive


    【解决方案1】:

    不同之处在于,如果您自己将该结果放入引用中,您可以在您自己的变量名中跟踪整数成员变量的变化,而无需调用函数。

    const &int x = myObject.getFoo();
    cout<<x<<endl;
    //...
    cout<<x<<endl;//x might have changed
    

    这可能不是最好的设计选择,并且返回引用(无论是否为 const)非常危险,以防返回从范围中释放的变量。因此,如果您返回一个引用,请注意确保它不是超出范围的变量。

    修饰符也有细微差别,但同样可能不是值得做的事情或预期的事情。

    void test1(int x)
    {
      cout<<x<<endl;//prints 1
    }
    
    void test2(const int &x)
    {
      cout<<x<<endl;//prints 1 or something else possibly, another thread could have changed x
    }
    
    int main(int argc, char**argv)
    {
      int x = 1;
      test1(x);
      //...
      test2(x);
      return 0;
    }
    

    所以最终的结果是,即使在参数传递之后,你也获得了变化。

    【讨论】:

    • “返回引用非常危险(无论是否为 const)” - 我很好奇,你如何返回更多重量级值?也许需要做是设计不佳的标志,但我倾向于通过 const ref 返回字符串。
    • @me - 我并不是说字符串是重量级的,我只是更愿意避免复制它们的(诚然可能很小的)开销。
    • 这样你必须考虑对象的生命周期。对于复杂的数据类型,这可能是值得的,但对于以与引用相同的成本复制的原语则不值得。
    • @sharptooth - 所以返回 const ref 不是天生的邪恶?
    • @Dominic Rodger:应该谨慎使用。
    【解决方案2】:

    对我来说,为原语传递 const 引用 是一个错误。要么你需要修改值,在这种情况下你传递一个非常量引用,或者你只需​​要访问这个值,在这种情况下你传递一个const .

    常量引用应该只用于复杂的类,因为复制对象可能是一个性能问题。对于原语,除非您需要修改变量的值,否则不应传递 reference。原因是 references 比 non-references 花费更多的计算时间,因为使用 references,程序需要查表才能找到对象的地址。当此查找时间短于复制时间时,引用是一种改进。

    通常,ints 和 addresses 在低级实现中具有相同的字节长度。所以复制一个int作为函数返回值的时间就相当于复制一个address的时间。但是在返回 int 的情况下,不会执行查找,因此会提高性能。

    【讨论】:

    • 真诚地问:编译器不会通过将原始 const refs 转换为 non-refs 来在内部优化这个吗?
    【解决方案3】:

    返回值和返回 const 引用的主要区别在于,您可以 const_cast 该引用并更改值。

    这是一个糟糕设计的例子,它试图创建一个智能设计,简单而简洁的设计就绰绰有余了。作者不只是返回一个值,而是让代码读者思考他可能有什么意图。

    【讨论】:

      【解决方案4】:

      没有太大的好处。我以前在框架或宏生成的 getter 和 setter 中看到过这一点。宏代码没有区分原始类型和非 POD 类型,只是将const type&amp; 用于设置器。我怀疑这是效率问题还是真正的误解;这可能是一个一致性问题。

      【讨论】:

        【解决方案5】:

        我认为这种类型的代码是误解了引用的概念并将其用于包括原始数据类型在内的所有内容的人编写的。我也看过一些这样的代码,看不出这样做有什么好处。

        【讨论】:

          【解决方案6】:

          没有任何意义和好处,除了

          void MyClass::setFoo(const int foo)
          void MyClass::setFoo(const int& foo)
          

          那么你将无法在 'setFoo' 实现中重用 'foo' 变量。我相信 'int&' 只是因为 Guy 习惯于通过 const 引用传递所有东西,这并没有错。

          【讨论】:

            猜你喜欢
            • 2018-06-18
            • 2012-02-06
            • 1970-01-01
            • 2015-02-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-11-25
            相关资源
            最近更新 更多