假设我有一个Foo
有std::string
member的课程str
。应该get_str
返回什么?
std::string Foo::get_str() const
{
return str;
}
或者
const std::string& Foo::get_str() const
{
return str;
}
C ++中什么更惯用?
假设我有一个Foo
有std::string
member的课程str
。应该get_str
返回什么?
std::string Foo::get_str() const
{
return str;
}
或者
const std::string& Foo::get_str() const
{
return str;
}
C ++中什么更惯用?
简短的回答是:这取决于:-)
从性能的角度来看,返回引用(通常)更好:您保存了新std::string
对象的创建。(在这种情况下,创建成本足够高,并且对象的大小足够高,足以证明做出这个选择至少值得考虑 - 但情况并非总是如此。使用更小的或内置类型,性能差异可能是可以忽略不计,或者按价值返回甚至可能更便宜)。
从安全的角度来看,返回原始值的副本可能会更好,因为恶意客户端可以抛弃 constness。如果该方法是公共 API 的一部分,则尤其要考虑这一点,即您(r 团队)无法完全控制返回值的使用方式(误用)。
拥有访问器方法的目标之一是尝试,至少在某种程度上,从它的接口抽象你的类实现。
按值返回更好,因为引用的对象没有生命周期问题。如果您决定不拥有std::string
成员,但例如 astd::stringstream
或动态创建 a std::string
,您不必更改界面。
通过引用返回const
与通过 const 引用获取参数并不相反,通过引用获取值const
不会将您的内部数据表示绑定到外部接口。
一般来说(除非存在已证明的性能问题)我会按价值返回。
首先存在语义差异,如果您的属性发生更改,您希望您的客户更新更改还是在调用函数时获取值?
存在明显的正确性问题,如果您通过引用返回,则调用该函数的实体可能会保留该引用并可能在您的对象被破坏后使用它(这不太好)。
另一个问题是多线程代码,如果一个线程在您更新变量时从 const 引用中读取很多麻烦。
无论如何,我认为最常见的用例是函数的调用者将值存储在变量中。
string val = obj->get_str();
// use val now
如果这是真的(与cout << obj->get_str()
没有变量的情况相反),val
即使您通过引用返回,您也总是必须构造一个新字符串,并且由于编译器可以执行RVO,因此按值版本不会低于 by-const-参考变体。
总结:如果您知道这是一个性能问题,并且您确定返回值的存储时间不会超过您的对象存在的时间,并且您不希望从不同的线程中使用,那么可以通过 const 引用返回.
按值返回意味着您不必将内部 std::string 存储在要返回的类中的某个位置。
在纯虚方法中,最好不要假设 std::string 会在那里,因此按值返回 std::string。
在一个明确有 std::string 成员的具体类中,您只是要返回对它的引用,为了提高效率,您可以通过 const 引用返回它。即使您以后必须更改它,您也不需要更改使用该类的功能。
在内部字符串可能在调用之间发生变化的多线程模型中,当然,您可能需要按值返回(假设该类的用户将在完成时获得字符串值的“快照”视图)通话)。
通过引用返回通常更有效。但是,我确实有一个不可变的引用计数字符串类,您可以有效地按值返回,而且我曾经经常使用它。
顺便说一句,有些人会建议通过 const 值返回 std::string 。我认为这不是最好的方法,因为它会阻止用户将其“交换”到局部变量中。
AFAIK,该规则与决定是通过值还是常量引用获取函数参数时使用的规则相同。如果sizeof
返回的值足够小,那么我倾向于使用返回一个副本,否则返回一个 const 引用。
我相信第二个实现(常量参考)是正确的:
str
.然而,第一种方法几乎同样有效。
通常,您应该按值(例如,int、short、char、long 等)返回 POD,并为更复杂的类型返回 const 引用:
int getData() const;
short getMoreData() const;
const std::string& getName() const;
const ComplexObject& getComplexData() const;
这取决于你想对返回值做什么。
如果您只想进行查询而不是修改str
.
const std::string& Foo::get_str() const
{
return str;
}
否则,请这样做:
std::string& Foo::get_str()
{
return str;
}
如果您想要 的副本/克隆,请str
使用以下命令:
std::string Foo::get_str() const
{
return str;
}