C ++ getter应该返回什么?

时间:2013-11-20 08:42:18

标签: c++ getter

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

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

    class MyType { /* ... */ };
    
    class MyClass
    {
      private:
         MyType mMyType;
    }
    

    我特别担心这种方法的以下用法。如果function()希望将其保存以供进一步使用,请您详细说明这可能会如何影响复制对象,以及悬挂引用和疯狂指针的危险。

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

    一个。适用于1.和2.

    {
      MyType t = myClass.getMyType();
      function(&t);
    }
    
    // is savedPointer still valid here?
    

    湾适用于1.和2.

    {
      const MyType& t = myClass.getMyType();
      function(&t);
    }
    
    // is savedPointer still valid here?
    

    ℃。适用于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?
    

    其中myClassMyClass类型的对象。

5 个答案:

答案 0 :(得分:19)

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

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

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

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

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

答案 1 :(得分:14)

一般情况下,除非您愿意,否则您应该更喜欢按值返回 明确地希望保证引用将指定 成员(公开部分实施,但是 在像std::vector<>::operator[])这样的情况下是可取的。返回 引用会阻止类中的后续更改,因为它意味着 你不能返回一个计算值。 (尤其如此 如果该类被设计为基类,则很重要 返回引用会为所有派生创建此限制 类。)

你应该通过指针返回的唯一时间是查找或 涉及的东西,可能返回必须返回 空指针。

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

答案 2 :(得分:3)

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

答案 3 :(得分:1)

应该避免按值返回,例如: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版本。非const版本是可选的,因为这意味着有人可以修改您的数据。这是我鼓励你使用的。

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

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

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

一个。在结束括号后,savedPointer将不再有效。

b,c和d。 savedPointer在结束括号后有效,但要注意它不应该超过myClass

答案 4 :(得分:0)

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

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

c)与b相同,但代码对2无效,因为您无法将const MyType&强制转换为MyType&。一般来说这是不好的做法,而且常量形式更容易接受。

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

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