返回成员变量的引用是不好的做法?

时间:2011-11-04 06:13:58

标签: c++ reference member-variables

以下据说比公共成员第一/第二更好。我相信这几乎一样糟糕。如果您正在提供一种方法来访问课外的私有变量,那么重点是什么?功能不应该是

T First(); void(or T) First(const T&)

样品:

// Example 17-3(b): Proper encapsulation, initially with inline accessors. Later
// in life, these might grow into nontrivial functions if needed; if not, then not.
//
template<class T, class U>
class Couple {
  Couple()           : deleted_(false) { }
  T& First()         { return first_; }
  U& Second()        { return second_; }
  void MarkDeleted() { deleted_ = true; }
  bool IsDeleted()   { return deleted_; }

private:
 T first_;
 U second_;
 bool deleted_;
};

3 个答案:

答案 0 :(得分:50)

有几个原因导致返回类的内部的引用(或指针)是坏的。从(我认为是)最重要的开始:

  1. 封装被破坏:泄漏实施细节,这意味着您无法再按照自己的意愿改变类内部。例如,如果您决定不存储first_,而是动态计算它,您将如何返回对它的引用?你不能,因此你被卡住了。

  2. 不变不再可持续(在非const引用的情况下):任何人都可以访问和修改随意引用的属性,因此您无法“监控”其更改。这意味着您无法维护此属性所属的不变量。从本质上讲,你的班级正在变成一个blob。

  3. 生命周期问题突然出现:在属性所在的原始对象不再存在之后,很容易保留属性的引用或指针。这当然是未定义的行为。例如,大多数编译器会尝试警告保持对堆栈上对象的引用,但我知道没有编译器能够为函数或方法返回的引用设置这样的警告:你是独立的。

    < / LI>

    因此,通常最好不要放弃引用或指向属性的指针。 甚至不是常数!

    对于较小的值,通常可以通过副本(inout)传递它们,特别是现在使用移动语义(在路上)。

    对于较大的值,它实际上取决于具体情况,有时代理可能会减轻您的麻烦。

    最后,请注意,对于某些课程,拥有公共成员并不是那么糟糕。封装pair成员的意义何在?当你发现自己编写的类只不过是一组属性(没有任何不变量)时,那么考虑将它们公之于众,而不是让我们所有的OO并为它们编写一个getter / setter对。

答案 1 :(得分:24)

如果template类型TU是大结构,那么按价值返回费用很高。但是,您是正确的,通过引用返回相当于授予对private变量的访问权限。要解决这两个问题,请将它们设为 const参考

const T& First()  const  { return first_; }
const U& Second() const  { return second_; }

P.S。此外,当没有setter方法时,在构造函数中保持变量未初始化是一种不好的做法。在原始代码中,First()Second()似乎是first_second_上的包装器,用于读/写两者。

答案 2 :(得分:7)

答案取决于人们想要做什么。返回引用是促进数据结构变异的便利方式。一个很好的例子是stl地图。它返回对元素的引用,即

std::map<int,std::string> a;
a[1] = 1;

没有什么可以阻止你做

auto & aref = a[1];

这一定是不好的做法吗?我不这么认为。我会说,如果没有它,你可以这样做。如果它让生活更方便和有效地使用它并且意识到你在做什么。