C++ 我应该更喜欢成员数据中的指针还是引用?

C++ 我应该更喜欢成员数据中的指针还是引用?,c++,reference,class-members,C++,Reference,Class Members,这是一个简单的例子来说明这个问题: class A {}; class B { B(A& a) : a(a) {} A& a; }; class C { C() : b(a) {} A a; B b; }; 所以B负责更新C的一部分。我通过lint运行代码,它抱怨引用成员:。 这涉及到对默认副本和赋值的处理,这是很公平的,但是默认副本和赋值对于指针来说也是不好的,所以没有什么优势 我总是尽可能地使用引用,因为裸体指针引入了不确定的

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

class A {};

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

class C
{
    C() : b(a) {} 
    A a;
    B b; 
};
所以B负责更新C的一部分。我通过lint运行代码,它抱怨引用成员:。
这涉及到对默认副本和赋值的处理,这是很公平的,但是默认副本和赋值对于指针来说也是不好的,所以没有什么优势

我总是尽可能地使用引用,因为裸体指针引入了不确定的关于谁负责删除该指针的信息。我更喜欢按值嵌入对象,但如果需要指针,我会在拥有指针的类的成员数据中使用auto_ptr,并将对象作为引用传递

通常,我只会在成员数据中使用指针,而指针可以为null或可以更改。对于数据成员来说,是否还有其他理由更喜欢指针而不是引用

包含引用的对象不应该是可分配的,因为引用在初始化后不应该更改吗?

是:包含引用的对象不应该是可分配的,因为引用在初始化后不应该更改吗

我的数据成员经验法则:

  • 永远不要使用引用,因为它会阻止赋值
  • 如果您的类负责删除,请使用boost的scoped_ptr(这比auto_ptr更安全)
  • 否则,请使用指针或常量指针

    • 对象很少允许赋值和其他类似比较的东西。如果你考虑一些商业模式,比如“部门”、“雇员”、“董事”之类的东西,那么很难想象一个雇员被分配给另一个雇员的情况。 因此,对于业务对象来说,最好将一对一和一对多关系描述为引用而不是指针

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

      因此,不存在“我们无法分配”因素。
      许多程序员只是习惯于使用指针,这就是为什么他们会找到任何参数来避免使用引用


      将指针作为成员将迫使您或您的团队成员在使用前反复检查指针,并给出“以防万一”的注释。如果指针可以为零,那么指针可能被用作某种标志,这是不好的,因为每个对象都必须发挥自己的作用。

      在一些重要的情况下,根本不需要可分配性。这些通常是轻量级的算法包装,可以在不离开范围的情况下简化计算。这些对象是引用成员的主要候选对象,因为您可以确保它们始终保持有效引用,并且不需要复制

      在这种情况下,确保赋值运算符(通常还有复制构造函数)不可用(通过继承
      boost::noncopyable
      或将其声明为private)

      然而,正如用户pts已经评论的那样,对于大多数其他对象来说,情况并非如此。在这里,使用引用成员可能是一个巨大的问题,通常应该避免。

      通常,我只会在成员数据中使用指针,而指针可以为null或可以更改。对于数据成员来说,是否还有其他理由更喜欢指针而不是引用


      对。代码的可读性。指针使成员更明显地是引用(讽刺的是:),而不是包含的对象,因为使用它时必须取消引用它。我知道有些人认为这是过时的,但我仍然认为这只是防止混乱和错误

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

      示例问题:

        <> LI>强制在每个构造函数的初始化列表中初始化引用:没有办法将这个初始化分解成另一个函数(直到C++ 0x,无论如何<强>编辑:< /强> C++现在拥有)
      • 引用不能为空。这可能是一个优势,但如果代码需要更改以允许重新绑定或使成员为null,则该成员的所有用途都需要更改
      • 与指针成员不同,由于重构可能需要智能指针或迭代器,所以无法轻松地替换引用
      • 每当使用引用时,它看起来像值类型(
        运算符等),但行为像指针(可以悬挂)-例如,不鼓励使用它
        • 我自己的经验法则:

          • 当您希望对象的生命周期依赖于其他对象的生命周期时,请使用引用成员:这是一种明确的方式,表示您不允许对象在没有另一个类的有效实例的情况下处于活动状态,因为没有赋值,并且有义务通过构造函数获得引用初始化这是一种设计类的好方法,不需要假设它的实例是另一个类的成员或不是另一个类的成员。您只需要假设它们的生命与其他实例直接相关。它允许您以后更改使用类实例的方式(使用new、作为本地实例、作为类成员、由管理器中的内存池生成等)
          • 在其他情况下使用指针:如果希望以后更改成员,请使用指针或常量指针,以确保只读取指向的实例如果该类型应该是可复制的,则无论如何都不能使用引用。有时还需要在特殊函数调用后初始化成员(例如init()),然后除了使用指针之外别无选择但是:在所有成员函数中使用断言可以快速检测错误的指针状态
          • 如果希望对象生存期依赖于外部对象的生存期,并且