首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >'const string& getName() const{}‘vs 'string getName() const{}'?

'const string& getName() const{}‘vs 'string getName() const{}'?
EN

Stack Overflow用户
提问于 2015-02-11 10:02:28
回答 3查看 1.5K关注 0票数 1

现在,这是高度概念性的。我不知道我是否正确理解了这一点,所以请帮助我理解其中的区别。

让我们假设name是一个私有的std::string数据成员,它由getName()访问器函数访问:

代码语言:javascript
复制
const string& getName() const {
       return name;  
}

现在,这将返回一个对name的引用,这只是别名的另一个单词。因此,将返回别名,即返回name数据成员。这是允许的吗?它会违背数据隐藏的全部目的吗?

换句话说,上述方法与传统方法到底有什么不同:

代码语言:javascript
复制
string getName() const {
     return name;
}

???

最后,实现前者而不是后者真的值得吗?

EN

回答 3

Stack Overflow用户

发布于 2015-02-11 10:17:29

首先,如果基础值可能发生变化,尤其是在多线程执行的上下文中,那么引用确实会有问题。因此,这几乎是一个基本的假设,即数据成员的值在对象的生命周期内不会更改。它实际上是一个常数。

现在,引用的一个主要问题是它暴露了实现细节,因此很难更改实现。

一个更具学术色彩的问题是,如果之前存在按值返回,或者只是因为它不寻常,它可能会破坏代码。例如。

代码语言:javascript
复制
const string s& = foo().name();

由于foo()通过值返回对象,而name()通过引用返回字符串,这为您提供了一个悬空的引用,而不是天真地预期的延长的生命周期。我称它为学术,因为我无法想象有人会写出这样的东西。尽管如此,墨菲定律和所有这些。

它可能不会(显著地)比值返回更有效,因为它不太可能仅仅用于初始化引用。

所以:

  • 可能不会显著提高效率,
  • 会阻止轻松更改实现,
  • 也有一个学术问题,会产生悬而未决的引用。

总而言之,就是不要。

这是过早的优化和复杂化。

票数 3
EN

Stack Overflow用户

发布于 2015-02-11 10:10:29

第一个允许调用者直接访问你的内部名称变量。假设它是常量,所以他们只能对它调用const方法。但您仍然希望外部调用者对您隐藏的内部数据进行操作吗?更糟糕的是,如果某个笨蛋决定const_cast字符串的内部数据缓冲区并破解它,该怎么办?

第二个函数返回一个内部name变量的副本。对任何调用者来说都是非常安全的。

我通常避开第一种类型,除非是琐碎的、低级的类型。但是不管怎样,琐碎的低级类型没有太多的复制开销。所以这意味着我从来没有写过这样的东西。

票数 1
EN

Stack Overflow用户

发布于 2015-02-11 10:06:47

常量引用返回更好,因为它不会复制字符串。我这么说的原因是因为这样的接口更灵活-如果需要的话,你总是可以将const引用复制到另一个字符串中,或者你可以将它作为一个引用-直到调用者。通过值返回一个成员,你总是被困在制作副本上。如果name很大或经常使用,那么它会影响性能,我认为性能是您使用C++的首要原因之一。

现在,其他答案提出了一些关于返回常量引用的负面观点,我认为这是无效的。

可以丢弃const的担忧是合理的,但丢弃const只是C++开发人员工具箱中的工具之一。为什么要把它拿走呢?如果有人真的想扰乱你的对象,他们总是可以在c++中通过直接寻址内存来做到这一点,所以设计你的代码来使你的调用者免于被调用是毫无意义的。抛弃const表明了这样做的意图,在我看来,这是完全可以的。这意味着调用者有一些非常具体的原因这样做,并且知道被抛出的const是针对非常数对象的,因此是安全的。

另一个答案中的学术例子太愚蠢了:

代码语言:javascript
复制
const string s& = foo().name();

同样,将代码设计为试图将调用者从自身中拯救出来,这将限制您使用C++的能力。如果真的想做上面的事情,正确的方法应该是

代码语言:javascript
复制
string s = foo().name();

因此,这一点也没有意义。

唯一有效的一点是,它在某种程度上公开了实现。然而,在我看来,效率的提高超过了这种担忧。

您真正应该问自己的是,使用name()的常见情况是什么?

通过回答这个问题,你将回答你应该使用哪种口味。

对我来说,它被称为name的事实意味着它将主要用于打印/日志记录和比较。因此,const引用显然是这里的赢家。

另外,看看外面的风格指南。它们中的大多数都会让你通过常量引用传递,并通过常量引用返回成员。如上所述,有很好的理由这样做。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28445353

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档