我应该更喜欢成员数据中的指针或引用吗?

这是一个简单的例子来说明这个问题:

class A {}; class B { B(A& a) : a(a) {} A& a; }; class C { C() : b(a) {} A a; B b; }; 

所以B负责更新C的一部分。我通过lint运行代码,并发出关于引用成员的声音: lint#1725 。 这里谈到关于默认的副本和分配,这是公平的,但默认的副本和分配也是坏指针,所以没有什么优势。

我总是尽可能地使用引用,因为裸指针不确定地引入谁负责删除指针。 我更喜欢通过值embedded对象,但如果我需要一个指针,我使用auto_ptr在拥有指针的类的成员数据,并作为参考传递对象。

我通常只会在指针可能为空或者可能改变时才在成员数据中使用指针。 有什么其他的理由喜欢指针比数据成员的引用?

是否真的说包含引用的对象不应该是可分配的,因为一旦初始化引用不应该被改变?

避免引用成员,因为它们限制类的实现可以做什么(包括,正如你所提到的那样,阻止赋值运算符的实现)并且没有给类提供什么好处。

示例问题:

  • 你不得不初始化每个构造函数的初始化列表中的引用:没有办法将这个初始化分解到另一个函数中( 直到C ++ 0x,无论如何 编辑: C ++现在有委托构造函数 )
  • 引用不能被反弹或为空。 这可能是一个优点,但是如果代码需要改变以允许重新绑定或者成员为空,则成员的所有用途都需要改变
  • 与指针成员不同,redirect可能需要引用不能轻易地被智能指针或迭代器所取代
  • 每当使用引用时它看起来像值types( .运营商等),但行为就像一个指针(可以悬垂) – 所以,例如谷歌风格指南不鼓励它

我自己的经验法则:

  • 当你希望对象的生命依赖于其他对象的生命时,使用一个引用成员 :这是一个明确的方式来说,如果没有另一个类的有效实例,你不允许对象生存 – 因为没有赋值和通过构造函数获取引用初始化的义务。 这是devise你的类的一个好方法,而不需要假定它的实例是成员或不是其他类的成员。 你只假定他们的生命直接与其他事例相关联。 它允许你稍后改变你如何使用你的类实例(使用新的,作为本地实例,作为类成员,由pipe理器中的内存池生成等)
  • 在其他情况下使用指针 :当您希望稍后更改成员时,请使用指针或常量指针以确保只读取指向的实例。 如果该types应该是可复制的,则无论如何您都不能使用引用。 有时你还需要在特殊的函数调用(例如init())之后初始化成员,然后你别无select,只能使用指针。 但是:使用断言你的所有成员函数来快速检测错误的指针状态!
  • 如果你希望对象的生命周期依赖于外部对象的生命周期,并且你也需要这个types是可复制的,那么在构造器中使用指针成员,但引用参数。这样你就可以在构造上指明这个对象的生命周期在参数的一生中,但实现使用指针仍然是可复制的。 只要这些成员只是通过复制来改变,而你的types没有默认的构造函数,那么types就应该满足这两个目标。

对象很less应该允许分配和比较等其他东西。 如果考虑一些像“部门”,“员工”,“总监”这样的对象的商业模式,很难想象一个员工被分配到其他人的情况。

所以对于业务对象来说,描述一对一和一对多的关系作为引用而不是指针是非常好的。

也许可以将一个或零个关系描述为一个指针。

所以没有“我们不能指定”那么因素。
很多程序员只是使用指针,这就是为什么他们会find任何参数来避免使用引用。

有一个指针作为一个成员将迫使你或你的团队成员在使用前一次又一次地检查指针,以“万一”的评论。 如果一个指针可以是零,那么指针可能被用作一种标志,这是不好的,因为每个对象都必须发挥自己的作用。

尽可能使用参考,必要时使用指示。

在一些重要的情况下,可分配性是根本不需要的。 这些通常是轻量级的algorithm包装,无需离开示波器便于计算。 这些对象是参考成员的主要候选对象,因为您可以确定它们始终拥有有效的引用并且永远不需要被复制。

在这种情况下,确保赋值运算符(通常也是复制构造函数)不可用(通过inheritanceboost::noncopyable或声明它们是私有的)。

然而,正如用户pts已经评论,大多数其他对象也是如此。 在这里,使用参考成员可能是一个巨大的问题,通常应该避免。

由于每个人似乎都在交出一般规则,所以我会提供两个:

  • 永远不要使用引用作为类成员。 我从来没有在自己的法典中这样做(除了向我自己certificate我是对的这个规则),并不能想象我会这样做的情况。 语义太混乱了,实际上并不是为什么而devise的。

  • 总是在向函数传递参数时使用引用(基本types除外),或者algorithm需要复制时。

这些规则很简单,而且很好地支持我。 我留下使用智能指针(但请,而不是auto_ptr)作为其他成员的规则。

是的: 是否真的说包含引用的对象不应该是可分配的,因为一旦初始化引用不应该被改变?

我的数据成员的经验法则:

  • 永远不要使用引用,因为它阻止了赋值
  • 如果你的类负责删除,使用boost的scoped_ptr(这比auto_ptr安全)
  • 否则,使用一个指针或const指针

我通常只会在指针可能为空或者可能改变时才在成员数据中使用指针。 有什么其他的理由喜欢指针比数据成员的引用?

是。 你的代码的可读性。 一个指针使得它更明显,成员是一个引用(讽刺:)),而不是一个包含的对象,因为当你使用它时,你必须去引用它。 我知道有些人认为这是老套的,但我仍然认为它只是防止混淆和错误。

我build议不要参考数据成员,因为你永远不知道谁会从你的class级中派生出什么,他们可能想要做什么。 他们可能不想使用被引用的对象,但作为一个引用,你迫使他们提供一个有效的对象。 我已经这样做了,足以停止使用引用数据成员。

由于其他答案中描述的限制,我不希望将引用用作数据成员。 就我个人而言,我使用以下经验法则:

1 – 要引用由std::shared_ptr拥有的外部资源,如果要共享所有权,则使用另一个std::shared_ptr ,如果不共享,则使用std::weak_ptr

2 – 否则,使用隐式转换为纯引用的std::reference_wrapper reference_wrapper。

除了在你的类中使用std::reference_wrapper ,你可以用它来在容器中存储引用(比如std::vector<std::reference_wrapper<int>> )。 请注意,你不能实例化一个std::vector<int&>