C++ getter 应该返回什么

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20091046/
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 22:54:50  来源:igfitidea点击:

What should a C++ getter return

c++getter

提问by Ferenc Deak

What is the best practice for a C++ getter method which is supposed to return a non trivial type, but a member which is of type class, or struct.

C++ getter 方法的最佳实践是什么,它应该返回一个非平凡的类型,但是一个类型为 class 或 struct 的成员。

  1. Return by value, such as: MyType MyClass::getMyType() { return mMyType; }
  2. Return by const reference: const MyType& MyClass::getMyType() { return mMyType; }
  3. Return by address: MyType* MyClass::getMyType() { return &mMyType; }
  1. 按值返回,例如: MyType MyClass::getMyType() { return mMyType; }
  2. 通过常量引用返回: const MyType& MyClass::getMyType() { return mMyType; }
  3. 按地址返回: MyType* MyClass::getMyType() { return &mMyType; }

where

在哪里

class MyType { /* ... */ };

class MyClass
{
  private:
     MyType mMyType;
}

I specifically worry about the following usages of this method. Can you please elaborate in details how this might affect copying the object, and the danger of dangling references and wild gone pointers if function()wants to save it for further usage.

我特别担心这种方法的以下用法。您能否详细说明这可能如何影响复制对象,以及如果function()想要保存它以供进一步使用时悬空引用和野生指针的危险。

MyType* savedPointer;

SomeType function(MyType* pointer) { savedPointer = pointer; };

a. valid for 1. and 2.

一种。对 1. 和 2. 有效。

{
  MyType t = myClass.getMyType();
  function(&t);
}

// is savedPointer still valid here?

b. valid for 1. and 2.

湾 对 1. 和 2. 有效。

{
  const MyType& t = myClass.getMyType();
  function(&t);
}

// is savedPointer still valid here?

c. valid for 1. and 2.

C。对 1. 和 2. 有效。

{
  MyType& t = myClass.getMyType();
  function(&t);
}

// is savedPointer still valid here?

d. valid for 3.

d. 有效期为 3。

{
  MyType* t = myClass.getMyType();
  function(t);
}

// is savedPointer still valid here?

where myClassis an object of type MyClass.

哪里myClass是类型的对象MyClass

采纳答案by Marcelo Cantos

You can provide both const and non-const versions:

您可以提供常量和非常量版本:

MyType       & MyClass::getMyType()       { return mMyType; }
MyType const & MyClass::getMyType() const { return mMyType; }

I wouldn't provide a pointer version, since that implies that the return value might be the null pointer, which it can never be in this instance.

我不会提供指针版本,因为这意味着返回值可能是空指针,在这个实例中它永远不会是空指针。

The real point, however, is that you are basically giving the caller direct access to the internal object. If this is your intent, then you may as well make the data member public. If it isn't, then you will need to work harder to hide the object.

然而,真正的重点是您基本上是让调用者直接访问内部对象。如果这是您的意图,那么您也可以将数据成员设为公开。如果不是,那么您将需要更加努力地隐藏对象。

One option is to retain the MyType const &accessor, but provide more indirect means to modify the internal object (setMyType(…)or something more tailored to the semantics that you are trying to express at the level of the containing class).

一种选择是保留MyType const &访问器,但提供更间接的方法来修改内部对象(setMyType(…)或者更适合您尝试在包含类级别表达的语义的东西)。

回答by James Kanze

In general, you should prefer return by value, unless you explicitly want to guarantee that the reference will designate a member (which exposes part of your implementation, but is desirable in cases like std::vector<>::operator[]). Returning a reference prevents later changes in class, since it means that you cannot return a calculated value. (This is especially important if the class is designed to be a base class, since returning a reference creates this restriction for all derived classes.)

通常,您应该更喜欢按值返回,除非您明确希望保证引用将指定一个成员(它公开了您的实现的一部分,但在类似情况下是可取的std::vector<>::operator[])。返回引用可防止类中的后续更改,因为这意味着您无法返回计算值。(如果类被设计为基类,这一点尤其重要,因为返回引用会为所有派生类创建此限制。)

The only time you should return by pointer is if a lookup or something is involved, which may return in having to return a null pointer.

您应该通过指针返回的唯一时间是如果涉及查找或某些事情,这可能会返回必须返回空指针。

Returning a reference to const may be a valid optimization, if the profiler indicates performance problems here, and the call site can also deal with a const reference (no modification of the returned value, no problems with lifetime of object). It must be weighed against the additional constraints on the implementation, of course, but in some cases, it is justified.

返回对 const 的引用可能是一个有效的优化,如果分析器在这里指出性能问题,并且调用站点也可以处理一个 const 引用(不修改返回值,对象生命周期没有问题)。当然,它必须与实施上的额外限制进行权衡,但在某些情况下,这是合理的。

回答by Javier Castellanos

I would always return a const reference. If you need to modify the value it is returning just use a setter function.

我总是会返回一个常量引用。如果您需要修改它返回的值,只需使用 setter 函数。

回答by Johan

Return by value, such as: MyType MyClass::getMyType() { return mMyType; }should be avoided as you will copy the content of your object. I do not see the gain you could have but I see the drawbacks on performance.

按值返回,例如:MyType MyClass::getMyType() { return mMyType; }应该避免,因为您将复制对象的内容。我没有看到您可以获得的收益,但我看到了性能上的缺点。

Return by const reference: const MyType& MyClass::getMyType() { return mMyType; }is more generaly used this way:

通过常量引用返回:const MyType& MyClass::getMyType() { return mMyType; }更普遍地使用这种方式:

const MyType& MyClass::getMyType() const { return mMyType; }
MyType& MyClass::getMyType() { return mMyType; }

Always provide the const version. The non-const version is optional as it means that someone can modify your data. It is what I would encourage you to use.

始终提供 const 版本。非常量版本是可选的,因为这意味着有人可以修改您的数据。这是我鼓励你使用的。

Return by address: MyType* MyClass::getMyType() { return &mMyType; }is mostly used when the data is optionally there. It often has to be checked before being used.

按地址返回:MyType* MyClass::getMyType() { return &mMyType; }主要用于数据可选时。通常在使用前必须进行检查。

Now, your use case, I would strongly advice not to keep a pointer save for more than a scope. I can often lead to ownership problems. I you have to do so, take a look to shared_ptr.

现在,您的用例,我强烈建议不要将指针保存在超过一个范围内。我经常会导致所有权问题。我你必须这样做,看看shared_ptr

For your examples, there is two cases:

对于您的示例,有两种情况:

a. savedPointer won't be valid any more after the closing brace.

一种。在结束大括号之后,savedPointer 将不再有效。

b,c, and d. savedPointer is valid after the closing brace, but beware it should not outlive myClass.

b、c 和 d。savedPointer 在右大括号之后有效,但请注意它不应超过myClass.

回答by Charlie

a) MyType t =will create a copy of the object for both 1 and 2. Saved pointer will not be valid once t is out of scope.

a)MyType t =将为 1 和 2 创建对象的副本。一旦 t 超出范围,保存的指针将无效。

b) The saved pointer will be valid for the case returning a reference, but invalid for the case returning an object. For the reference, the lifetime of the pointer would be the same as myClass. Of course &t on a const ref would be a const t* not a t* and so would fail to cast in your call to function(MyType*).

b) 保存的指针对返回引用的情况有效,但对返回对象的情况无效。对于引用,指针的生命周期与 myClass 相同。当然, const ref 上的 &t 将是 const t* 而不是 at* ,因此在您对function(MyType*).

c) Same as b, though the code is invalid for 2 because you can't cast a const MyType&to a MyType&. Generally this would be bad practice and the const form would be more acceptable.

c) 与 b 相同,但代码对 2 无效,因为您不能将 a 转换const MyType&为 a MyType&。通常这将是不好的做法,const 形式会更容易接受。

d) savedPointer will have the same lifetime as myClass.

d) savedPointer 将与 myClass 具有相同的生命周期。

I'd generally lean toward either returning a reference or a const reference depending on what you expect to be able to do with the return value. If you return a reference (non-const), you can do things like: myClass.getMyType() = ..., while if you return a const reference, the object is read-only.

我通常倾向于返回引用或 const 引用,具体取决于您期望能够对返回值做什么。如果您返回一个引用(非常量),您可以执行以下操作:myClass.getMyType() = ...,而如果您返回一个常量引用,则该对象是只读的。