C++ 将 std::string 作为常量引用返回

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13507698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:25:12  来源:igfitidea点击:

Return std::string as const reference

c++stringreferenceconststdstring

提问by Aneesh Narayanan

I have a doubt on returning std::string as const reference.

我对返回 std::string 作为常量引用有疑问。

class sample
{
public:
  std::string mString;
  void Set(const std::string& s)
  {
    mString = s;
  }
  std::string Get()
  {
    return mString;
  }
 };

In the Set function I am passing the std::string as const reference, const because its value is not changing inside the function.

在 Set 函数中,我将 std::string 作为 const 引用传递,const 因为它的值在函数内部没有改变。

And In Get function, actually I am confused here. Return std::string as value makes more sense. But I am not sure that, by passing the string as const reference makes any advantages. By returing string as reference will increase the exectuion speed, I think So, but I am not sure. But returning it as 'const makes any benefit for this?

在 Get 函数中,实际上我在这里感到困惑。返回 std::string 作为值更有意义。但我不确定,通过将字符串作为 const 引用传递是否有任何好处。通过返回字符串作为参考将提高执行速度,我认为是的,但我不确定。但是将它返回为 'const 对此有什么好处吗?

回答by Dietmar Kühl

The problem of deciding how to return a non-trivial object from some sort of a container is actually non-trivial:

决定如何从某种容器返回一个非平凡对象的问题实际上是非平凡的:

  • If the class from which you return your value imposes any sort of constraint on the object, you can't return a non-constreference because it would loose the possibility to enforce its invariants. Clearly, returning an object by non-constreference is only viable if object the member function is called on is also non-const.
  • Exposing a constreference to an object would avoid the problem with the invariants but still implies that an object of the corresponding type is actually kept internally as an implementation detail.
  • Returning an object by value may incur a significant cost for copying the object.
  • 如果返回值的类对对象施加了任何类型的约束,则不能返回非const引用,因为它会失去强制执行其不变量的可能性。显然,const只有在调用成员函数的对象也是 non- 时,通过非引用返回对象才是可行的const
  • 公开const对对象的引用将避免不变量的问题,但仍然意味着相应类型的对象实际上作为实现细节在内部保留。
  • 按值返回对象可能会导致复制对象的大量成本。

If you class is further a viable monitoryou definitely want to return the object by value because otherwise the object can be mutated before the caller had any chance to copy it.

如果您的班级进一步成为一个可行的监视器,您肯定希望按值返回对象,否则该对象可能会在调用者有机会复制它之前发生变异。

Basically, none of the choices is ideal. When in doubt, I return by value unless the object is known to be expensive to copy in which case I mightreturn by const&.

基本上,没有一个选择是理想的。如有疑问,我会按值返回,除非已知该对象的复制成本很高,在这种情况下我可能会const&.

回答by Angew is no longer proud of SO

Returning by reference or const reference has no speed difference - both are very fast as they just return a reference to the original object, no copying is involved.

通过引用或常量引用返回没有速度差异 - 两者都非常快,因为它们只返回对原始对象的引用,不涉及复制。

An object returned by (non-const) reference can be modified through that reference. In your specific example, mStringis public, so it can be modified anyway (and directly). However, the usual approach with getters and setters (and the primary reason for their introduction) is encapsulation - you only allow access to your data members through the getter/setter, so that you can detect invalid values being set, respond to value changes and just generally keep the implementation details of your class hidden inside it. So getters normally return by const reference or by value.

由(非常量)引用返回的对象可以通过该引用进行修改。在您的具体示例中,mString是公开的,因此无论如何都可以(并且直接)对其进行修改。但是,getter 和 setter 的常用方法(以及引入它们的主要原因)是封装——您只允许通过 getter/setter 访问您的数据成员,以便您可以检测设置的无效值、响应值更改和通常只是将类的实现细节隐藏在其中。因此 getter 通常通过常量引用或值返回。

However, if you return by const reference, it binds you to alwayskeep an instance of std::stringin your class to back up the reference. That is, even if you later want to redesign your class so that it computes the string on the fly in the getter instead of storing it internally, you can't. You'd have to change your public interface at the same time, which can break code using the class. For example, as long as you return by const-reference, this is perfectly valid code:

但是,如果您通过 const 引用返回,它会绑定您始终std::string在您的类中保留一个实例来备份该引用。也就是说,即使您以后想要重新设计您的类,以便它在 getter 中动态计算字符串而不是将其存储在内部,您也不能。您必须同时更改公共接口,这可能会破坏使用该类的代码。例如,只要您通过常量引用返回,这是完全有效的代码:

const std::string *result = &aSample.Get();

This code will of course produce a dangling pointerno longer compileif Get()is changed to return by value instead of const reference. (thanks to Steve Jessop for correcting me)

如果更改为按值返回而不是 const 引用,则此代码当然会产生不再编译的悬空指针Get()(感谢 Steve Jessop 纠正我)

To sum up, the approach I would take is to make mStringprivate. Get()can return by value or by const-reference, depending on how certain you are that you'll always have a string stored. The class would then look like this:

总而言之,我会采取的方法是mString私有化。Get()可以按值或按常量引用返回,这取决于您对始终存储字符串的确定程度。该类将如下所示:

class sample
{
  std::string mString;

public:
  void Set(const std::string &s)
  {
    mString = s;
  }
  std::string Get() const
  {
    return mString;
  }
};

回答by Mark Ingram

The most common thing to do here would be to return the value as a const-reference, then you can use a reference or copy the value as necessary:

这里最常见的做法是将值作为常量引用返回,然后您可以根据需要使用引用或复制值:

const std::string& Get() const
{
    return mString;
}

sample mySample;
const std::string &refString = mySample.Get(); // Const-reference to your mString
const std::string copyString = mySample.Get(); // Copy of your mString

If you really needto return a copy of the string, then you can avoid copying the string return value by utilising "The Most Important Const":

如果您确实需要返回字符串的副本,则可以通过使用“最重要的常量”来避免复制字符串返回值:

sample mySample;
const std::string &myString = mySample.Get();
// myString is now valid until it falls out of scope, even though it points to a "temporary" variable

回答by chill

Return it as a reference. If a copy is needed, it certainly can be made from that reference.

将其作为参考返回。如果需要副本,当然可以从该参考资料中制作。