C++getter应该返回什么

What should a C++ getter return

本文关键字:什么 返回 C++getter      更新时间:2023-10-16

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

  1. 按值返回,如:MyType MyClass::getMyType() { return mMyType; }
  2. 常量引用返回: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?

其中CCD_ 5是类型为CCD_。

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

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

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

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

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

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

您应该通过指针返回的唯一时间是如果涉及到一些东西,这些东西可能会在不得不返回时返回空指针。

如果探查器在此处指示性能问题,并且调用站点还可以处理const引用(不修改返回的值,对象的生存期没有问题)。它必须根据执行,当然,但在某些情况下,它是合理的。

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

应避免按值返回,例如:MyType MyClass::getMyType() { return mMyType; },因为您将复制对象的内容。我看不出你能得到什么好处,但我看到了表现上的缺点。

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

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

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

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

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

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

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

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

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() = ...,而如果返回常量引用,则对象是只读的。