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

class A {};

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

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

所以B负责更新C的一部分。我通过 lint 运行了代码,它抱怨引用成员: 皮棉#1725。这讨论了如何处理默认复制和赋值,这很公平,但是默认复制和赋值对于指针来说也很糟糕,因此几乎没有什么优势。

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

当指针可能为空或可能更改时,我通常只会在成员数据中使用指针。对于数据成员,还有其他原因更喜欢使用指针而不是引用吗?

由于引用一旦初始化就不应更改,因此包含引用的对象不应该是可分配的,这是真的吗?

有帮助吗?

解决方案

避免引用成员,因为它们限制了类的实现可以执行的操作(包括,正如您提到的,阻止赋值运算符的实现),并且对类可以提供的功能没有任何好处。

问题示例:

  • 您被迫初始化每个构造函数的初始化列表中的引用:没有办法将这个初始化分解到另一个函数中(无论如何,直到 C++0x 编辑: C++ 现在有 委托构造函数)
  • 引用不能反弹或为空。这可能是一个优点,但如果需要更改代码以允许重新绑定或使成员为空,则该成员的所有使用都需要更改
  • 与指针成员不同,引用不能轻易地被智能指针或迭代器替换,因为重构可能需要
  • 每当使用引用时,它看起来就像值类型(. 运算符等),但行为类似于指针(可以悬挂) - 所以例如 谷歌风格指南 阻止它

其他提示

我自己的经验法则:

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

物件很少应该允许分配和其他的东西等的比较。如果你考虑像“部门”的对象,“雇员”,“导演”了一些商业模式,这是很难想象当一个员工将被分配给其他的情况。

因此,对业务对象这是非常好的描述一个对一个,一个一对多作为参考的关系,而不是指针。

和可能它是确定描述一或零作为指针的关系。

因此,没有“我们不能将”然后因素。结果 很多程序员只是用得到的指针,这就是为什么他们会找到任何参数,以避免使用时参考。

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

在几个重要的情况下,简单地不需要转让性。这些通常是轻量级的算法封装便于计算不留范围。这样的对象仅供参考成员主要候选者,因为你可以确信,他们总是持有的有效的参考和永远需要被复制。

在这种情况下,确保以使赋值运算(通常也拷贝构造)不可用(由从boost::noncopyable继承或声明它们私有的)。

然而,由于用户的积分已经评论,同样是不是大多数其他对象真。在这里,用基准部件可以是一个巨大的问题,一般应避免。

由于每个人似乎都在发布一般规则,我将提供两条:

  • 永远不要使用引用作为类成员。我从未在自己的代码中这样做过(除了向自己证明我在这条规则中是正确的),并且无法想象我会这样做的情况。语义太混乱了,这确实不是参考设计的目的。

  • 在将参数传递给函数时(基本类型除外)或算法需要副本时,始终始终使用引用。

这些规则很简单,对我很有帮助。我将有关使用智能指针(但请不要使用 auto_ptr)作为类成员的规则留给其他人。

是: 由于引用一旦初始化就不应更改,因此包含引用的对象不应该是可分配的,这是真的吗?

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

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

我将通常只使用在构件数据指针时,指针可以是空值或可以改变。是否有任何其他原因更喜欢引用指针数据成员?

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

我建议不要引用数据成员becasue你永远不知道谁将会从你的类派生,他们可能想要做什么。他们可能不希望使用所引用的对象,但被引用你已经迫使他们提供一个有效的对象。 我这样做对自己足够的停止使用参考数据成员。

如果我理解正确的问题...

<强>参考作为函数参数,而不是指针: 正如您所指出的,一个指针不说清楚谁拥有指针的清理/初始化。当需要一个指针更喜欢共享一点上,它的C ++ 11的一部分,并且当所述数据的有效性未通过类接受指向的数据的寿命保证一个的weak_ptr .;还的C ++ 11的一部分。 使用引用作为函数参数保证该基准不为空。你必须颠覆了语言功能来解决这个问题,我们不关心松散的大炮编码器。

<强>参考一个成员变量: 正如上文中关于数据的有效性。此担保所指向的数据,然后引用,是有效的。

中的代码移动到一个较早点变量有效性的责任,不仅清理后的代码(在您的示例中的A类),但也明确使用人。

在您的例子,这是一个有点混乱(我真的试图找到一个更更清晰的实施),用B使用A保证为B的寿命,因为B是A的一个成员,所以参考加强了这一和是(可能)更清晰。

和万一(这是一个低可能罩,因为这将没有任何意义在您的代码上下文中),另一种选择,使用非引用的,非指针的参数,将复制A,和使范例没用 - 我真的不认为你的意思是这是一种替代

此外,这也保证你不能够改变所引用的数据,其中,一个指针可以被修改。一个const指针将工作,只有当引用/指针数据不是可变的。

指针是如果不保对于B将A参数被设置,或者可以被重新分配是有用的。有时,一个微弱的指针是实施太啰嗦了,相当数量的人不知道或者是weak_ptr的是什么,或者只是不喜欢他们。

撕开此答案,请:)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top