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

49 c++ reference member-variables

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

T First(); void(or T) First(const T&)
Run Code Online (Sandbox Code Playgroud)

样品:

// 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_;
};
Run Code Online (Sandbox Code Playgroud)

Mat*_* M. 55

将引用(或指针)返回到类的内部是不好的有几个原因.从(我认为是)最重要的开始:

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

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

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

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

对于较小的值,通常足以通过复制(两者in和两者out)传递它们,特别是现在使用移动语义(在路上).

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

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

  • +1,但没有提供访问者计数器理由:你可以添加仪器的号召,这使得它更容易找到对象所在的代码更新的地方,或附加调试器来检测的问题. (2认同)

iam*_*ind 26

如果template类型TU大结构然后按价值返回是昂贵的.但是你是正确的,通过引用返回相当于提供对private变量的访问.要解决这两个问题,请将它们const作为参考:

const T& First()  const  { return first_; }
const U& Second() const  { return second_; }
Run Code Online (Sandbox Code Playgroud)

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

  • [此链接](http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/)对值和R值的传递有一些有趣的见解. (3认同)

Ram*_*mbi 7

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

std::map<int,std::string> a;
a[1] = 1;
Run Code Online (Sandbox Code Playgroud)

什么都阻止你做

auto & aref = a[1];
Run Code Online (Sandbox Code Playgroud)

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