2

可能重复:
访问器应该返回值还是常量引用?

首先,让我们忽略 setter 和 getter 是/不是邪恶的。:)

我的问题是,如果我有一个包含某个std::容器作为成员的类,比如说string,getter 的返回类型应该是什么?const T&与性能原因相比,我更喜欢T...我知道大多数时候用户无论如何都会制作副本,但我想并非总是如此。我错了吗?

所以总的来说什么更好:

std::string get_name() const;

或者

const std::string& get_name() const;
4

4 回答 4

7

返回一个常量引用。如果用户想要制作副本,请不要吝啬你的背影。

于 2012-09-30T23:37:54.147 回答
2

这是考虑因素:

1)返回副本string。然后文档很简单(“返回...的当前值”)并且函数很慢(我怀疑在很多情况下编译器足够聪明以省略副本,即使返回值仅在一个单表达式,理论上编译器可以识别string为无副作用副本的值类型,也可以证明在调用者使用副本期间引用不能改变,因此使用引用代替。但它会做这一切吗?)。

2)返回参考const string&。然后文档很复杂,(“返回对string包含的当前值的对象的引用......此引用在以下时间保持有效......它继续包含该时间的以下子集的相同值...... ”)。如果调用者不需要副本,则该函数很快。该类的实现几乎被限制为始终将该字符串存储为string数据成员,因为否则它将没有任何东西可以在合适的生命周期内返回。

别名可能很快(如果它避免复制)但很复杂(因为引用可以更改或消失),因此返回引用的函数可能很快但很复杂。此外,(1) 是“返回对象属性的 getter”,而 (2) 是“返回对象私有成员的 getter”。所以如果吸气剂是邪恶的,那么(2)比(1)更邪恶。

I would generally return the reference if the getter is essentially there as a hack for other tightly-coupled classes to get at the data, or if the class has very obvious semantics for when it will change, for example "never during the lifetime of the object", or if the string is expected to be so huge that it's reasonable to expose it by reference simply because taking a copy of it should be rare and so callers will be expecting view behavior rather than value behavior. I'd probably return the value if the interface is supposed to be compatible-forever, just to be safe, unless the class I'm writing is explicitly designed as "a thing that holds a big string and does X for you whilst still letting you see the string".

不可变的垃圾收集字符串解决了这个问题,这可能是它们对高级语言设计者有吸引力的原因之一。

于 2012-10-01T01:08:44.660 回答
1

这取决于 getter 的最常见用途。

如果从 get 操作的那一刻起直到程序结束都将使用该字符串,则可能会建议进行复制操作,因为您不想向用户“做出关于字符串的生命周期的承诺”。

如果要立即使用该字符串,请使用引用。

如果您的整个系统正在使用某个字符串存储库,则可以确保所有字符串的生命周期都是已知的。您可以安全地从该存储库返回引用。

于 2012-09-30T23:42:22.090 回答
1

一般来说,一个 const 引用是理想的。正如Kerrek 所说,如果他们需要一份副本,他们可以自己制作。这可能导致问题的唯一地方完全是参考接收者的责任。例如,当一个 const 引用 var 正在接收一个返回 const 引用的对象成员的结果,并且该对象后来被独立于引用变量的生命周期而被销毁时,您已经有效地“记住”了一个指针(松散术语)不再有效;IE :

const std::string& myref = myobj->getString();
...
delete myobj;

但是您应该了解这一点(因为您正在编写代码),因此应该首先计划避免它。他们应该制作副本而不是获取参考,无论如何返回参考仍然是最佳实践。

于 2012-09-30T23:46:13.267 回答