C++ ';常量字符串&;getName()常量{}';vs';字符串getName()常量{}';?

C++ ';常量字符串&;getName()常量{}';vs';字符串getName()常量{}';?,c++,C++,现在,这是高度概念化的。我不知道我是否理解正确,所以请帮助我理解其中的区别 让我们假设name是一个私有std::string数据成员,由getName()访问器函数访问: const string& getName() const { return name; } 现在,这将返回一个引用,它只是别名的另一个单词,指向name。因此,将返回一个别名,即返回名称数据成员。这是允许的还是会破坏数据隐藏的全部目的 换言之,上述方法与传统方法究竟有何区别: string ge

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

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

const string& getName() const {
       return name;  
}
现在,这将返回一个引用,它只是别名的另一个单词,指向
name
。因此,将返回一个别名,即返回
名称
数据成员。这是允许的还是会破坏数据隐藏的全部目的

换言之,上述方法与传统方法究竟有何区别:

string getName() const {
     return name;
}


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

常量引用返回更好,因为它不复制字符串。我之所以这样说,是因为接口以这种方式更加灵活-如果需要,您可以随时将const引用复制到另一个字符串中,或者您可以将其用作引用-直到调用方。按值返回成员时,您总是要复制副本。如果 No> 是大的或经常使用的,那么它会影响性能,我认为性能是你首先使用C++的原因之一。 现在,其他答案提出了一些关于返回常量引用的负面观点,我认为这是无效的

你可以抛弃这个常量,这是有效的,但是抛弃const只是C++开发者工具箱中的工具之一。为什么要把它拿走?如果有人真的想和你的对象乱搞,他们可以直接在C++中通过直接处理内存来完成,所以设计你的代码来保存你的呼叫者是没有意义的。扔掉const显示了这样做的意图,在我看来是完全可以的。这意味着调用方有一些非常具体的原因这样做,并且知道被丢弃的常量是用于非常量对象的,因此是安全的

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

const string s& = foo().name();

再次,设计代码试图从自己保存呼叫者,这限制了C++的能力。如果一个人真的想做上述事情,正确的方法是

string s = foo().name();
所以这一点也没有意义

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

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

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

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


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

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

第二个返回内部名称变量的副本。对任何来电者来说都非常安全


我通常会避开第一种类型,除了琐碎的、低级的类型。但是,简单的低级类型无论如何都不会有太多的复制开销。这意味着我从来没有写过这样的东西

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

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

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

const string s& = foo().name();
使用
foo()
通过值返回对象,以及
name()
通过引用返回字符串,这将为您提供一个悬空引用,而不是天真地期望延长的生命周期。我称之为学术性的,因为我无法想象有人会这样写。不过,墨菲定律和所有这些

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

因此:

  • 可能效率不会明显提高

  • 防止轻松更改实施

  • 也有一个学术问题,产生悬而未决的参考文献

总之,不要这样做


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

不要这样做。你想说什么?一个是副本,一个是reference@JamesMoore:一个是副本,一个是引用的副本,怎么样?另一个需要考虑的问题是,首先你真的需要一个getter函数吗?“更好”这是一个观点问题,每个版本都有其优缺点。除了是否制作副本之外,还有其他考虑因素。这可能还取决于对象最常见的用例。@MattMcNabb。没错,我对我的答案进行了更好的解释……没有双关语;)它可能不会比值返回更有效,确切地说是b因为它不太可能仅仅用于初始化引用-我强烈反对这一点。它被称为
name
,这一事实意味着它很可能被用于比较、打印/记录、作为地图中的一个键等。这些用途中的大多数将更加有效。现在,你的学术示例只是在推动它……你所拥有的一切做我