C++ getter 应该返回什么

问题描述 投票:0回答:5

C++ getter 方法的最佳实践是什么,该方法应该返回一个非平凡类型,而是一个类或结构类型的成员。

  1. 按值返回,如:
    MyType MyClass::getMyType() { return mMyType; }
  2. 通过 const 引用返回:
    const MyType& MyClass::getMyType() { return mMyType; }
  3. 返回地址:
    MyType* MyClass::getMyType() { return &mMyType; }

哪里

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

class MyClass
{
  private:
     MyType mMyType;
}

我特别担心这个方法的以下用法。您能否详细说明这可能如何影响复制对象,以及如果

function()
想要保存它以供进一步使用,则悬空引用和野生指针的危险。

MyType* savedPointer;

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

a.适用于 1. 和 2.

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

// is savedPointer still valid here?

b.适用于 1. 和 2.

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

// is savedPointer still valid here?

c.适用于 1. 和 2.

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

// is savedPointer still valid here?

d。有效期为 3 次。

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

// is savedPointer still valid here?

其中

myClass
MyClass
类型的对象。

c++ getter
5个回答
31
投票

您可以提供 const 和非 const 版本:

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

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

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

一种选择是保留

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


25
投票

一般来说,您应该更喜欢按值返回,除非您 明确想要保证引用将指定 一个成员(它公开了您的实现的一部分,但是 在类似

std::vector<>::operator[]
的情况下是理想的)。返回 引用可以防止以后对类进行更改,因为这意味着 您无法返回计算值。 (这尤其是 如果该类被设计为基类,则很重要,因为 返回引用会为所有派生创建此限制 课程。)

唯一应该通过指针返回的时间是查找或 涉及到一些事情,可能会导致必须返回 空指针。

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


3
投票

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


2
投票

应避免按值返回,例如:

MyType MyClass::getMyType() { return mMyType; }
,因为您将复制对象的内容。我看不到您可以获得的收益,但我看到了性能方面的缺点。

通过 const 引用返回:

const MyType& MyClass::getMyType() { return mMyType; }
更常用这种方式:

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

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

按地址返回:

MyType* MyClass::getMyType() { return &mMyType; }
主要用于数据可选存在的情况。使用前经常需要检查。

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

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

a.在右大括号之后,savedPointer 将不再有效。

b、c 和 d。 savePointer 在右大括号之后有效,但要注意它不应该比其寿命长

myClass


0
投票

a)

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

b) 保存的指针对于返回引用的情况有效,但对于返回对象的情况无效。作为参考,指针的生命周期与 myClass 相同。当然,const ref 上的 &t 是 const t* 而不是 t*,因此无法在对

function(MyType*)
的调用中进行强制转换。

c) 与 b 相同,但代码对于 2 无效,因为您无法将

const MyType&
转换为
MyType&
。一般来说,这是不好的做法,const 形式更容易被接受。

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

我通常倾向于返回引用或 const 引用,具体取决于您期望能够对返回值执行什么操作。如果您返回一个引用(非常量),您可以执行以下操作:

myClass.getMyType() = ...
,而如果您返回一个常量引用,则该对象是只读的。

© www.soinside.com 2019 - 2024. All rights reserved.