访问者应该返回值还是常量引用?

fre*_*low 16 c++ reference accessor return-value

假设我有一个Foostd::string成员的班级str.应该get_str返回什么?

std::string Foo::get_str() const
{
    return str;
}
Run Code Online (Sandbox Code Playgroud)

要么

const std::string& Foo::get_str() const
{
    return str;
}
Run Code Online (Sandbox Code Playgroud)

什么是C++更惯用?

Pét*_*rök 16

简短的回答是:它取决于:-)

从性能的角度来看,返回引用(通常)更好:保存新std::string对象的创建.(在这种情况下,创建成本足够高,并且对象的大小足够高,足以证明这个选择至少值得考虑 - 但情况并非总是如此.对于较小或内置类型,性能差异可能是可忽略不计,或按价值返还甚至可能更便宜).

从安全的角度来看,返回原始值的副本可能会更好,因为constness可能被恶意客户端抛弃.如果该方法是公共API的一部分,则尤其要考虑这一点,即您(团队)无法完全控制返回值的使用方式(错误).

  • +1,这是一个很好的观点,先生。事实上,API 代码永远不应该公开私有成员,即使是间接公开。 (2认同)
  • 你基本上必须相信你的 API 用户不会绕过 `const` 修饰符。他们是在用脚射击自己,如果代码不起作用,那是他们自己的错。也就是说,我不认为 *隐藏数据* 是不返回 `const` 的好理由。 (2认同)

CB *_*ley 7

使用访问器方法的目标之一是至少在某种程度上尝试从其接口中抽象出类实现.

按值返回更好,因为引用的对象没有生命周期问题.如果你决定不拥有一个std::string成员,但是,比如a std::stringstream或者std::string即时创建你不必更改界面.

通过const引用返回与通过const引用获取参数的方式不同,通过引用获取值const不会将内部数据表示与外部接口绑定.


Mot*_*tti 5

一般来说(除非有已证明的性能问题)我会按值返回。

首先,存在语义差异,如果您的属性发生更改,您是否希望客户端更新更改或在调用函数时获取值?

存在明显的正确性问题,如果您通过引用返回,调用该函数的实体可能会保留该引用,并可能在对象被破坏后使用它(这不太好)。

另一个问题是多线程代码,如果一个线程在您更新变量时从 const 引用中读取数据,则会带来很多麻烦。

无论如何,我认为最常见的用例是函数的调用者将值存储在变量中。

string val = obj->get_str();
// use val now
Run Code Online (Sandbox Code Playgroud)

cout << obj->get_str()如果这是真的(与没有变量的情况相反) val,即使您通过引用返回,您也始终必须构造一个新字符串,并且由于编译器可以执行RVO ,因此按值版本不会低于按常量的性能参考变体。


结论:如果您知道这是一个性能问题,并且确定返回值的存储时间不会超过您的对象存在的时间,并且您不希望从不同的线程中使用它,那么可以通过 const 引用返回。