16

在我维护的一个项目中,我看到很多这样的简单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 '&'

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

4

6 回答 6

21

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

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

所以最终的结果是,即使在参数传递之后,您也可以获得更改。

于 2009-03-23T09:46:39.950 回答
8

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

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

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

于 2009-03-23T15:25:57.607 回答
5

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

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

于 2009-03-23T09:40:35.970 回答
4

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

于 2009-03-23T14:44:28.627 回答
2

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

于 2009-03-23T09:48:03.220 回答
0

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

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

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

于 2009-03-23T09:55:00.583 回答