成员变量使用指针还是引用?

5

我需要在c++ linux中进行澄清。

我有一个C1类和另一个C2类C1类将拥有对C2类的引用。

class C1
{

   C2 &obj ;

}

我在考虑两个选择:

  1. 直接将C2的引用保存为C2 &obj;
  2. 创建C2的指针,如c2* obj;

哪个更好?它们有什么区别?选择哪个?


1
类似的问题 https://dev59.com/enNA5IYBdhLWcg3wn_Q1 - Dani van der Meer
4个回答

2
尽量避免使用引用成员变量。与引用和指针之间的不同一样,如果您有一个引用成员,那么它必须在创建类对象时进行初始化,因为无法像指针成员那样进行延迟初始化,因为引用不能为NULL且不能被重新分配位置,而指针成员可以在需要时懒惰地指向C2实例。
此外,请注意,还有其他副作用。一旦您有了引用成员,编译器将不会生成复制赋值运算符(=),您必须自己提供一个。在这种情况下,确定您的=操作符应该执行什么操作是很麻烦的。
对于大多数实际用途(除非您真的担心由于C2大小而导致的高内存使用),只需作为C1的成员持有C2的实例即可,而不是指针或引用成员,这样可以省去许多关于引用/指针成员带来的其他问题的烦恼,尽管会增加额外的内存使用。
如果必须使用指针,请确保使用智能指针而不是裸指针,这将使指针的使用更加容易。

出于您提到的确切原因,使用指针作为成员比使用引用更可取。使用引用是一种不太通用的解决方案,可能会导致意外行为。我建议始终避免使用引用作为成员。 - Maxim Egorushkin
我想补充一下,在某些情况下,引用的限制恰好符合您尝试使用代码描述的内容,例如与另一个对象整个生命周期相关联的对象(例如具有互斥对象的互斥锁对象)。在这种情况下,使用引用更加明确。 - Kos

0
指针相对于引用有两个主要优点。指针可以为空,指针可以移动(例如使用++运算符)。但是在这里移动并没有帮助。
如果在实例化C1时不知道类C2,则应使用指针,因为您无法初始化引用,但是指针可以初始化为空。
像Als所说,当C2实例可能更改时,我也建议使用指针。在这种情况下可以使用引用,但我认为指针是一种更“干净”的解决方案。

3
指针不需要初始化并不是一个优点。 - dangerousdave

0

两者都不好。如果您有任何指向类外分配的东西的指针或引用成员变量,那么这很可能意味着程序设计在某种程度上存在缺陷。

我能想到的一个合理情况是,当您具有某种特殊的外部垃圾收集器功能时。(例如C++ Builder自动分配/释放堆上的VCL组件。)

另一种情况是,在模拟C结构的C++类或在另一个类中编写私有类时,可能会有效。

但是,最有可能的是,需要指向类外部的东西来自于有缺陷的程序设计。我会仔细考虑我的代码为什么需要这样做,并尽可能添加const正确性到指针,即const *c2 const obj;

如果您有这样的特殊成员指针,则还必须手动编写类的复制构造函数、赋值运算符和析构函数。

编辑:这种做法不好的原因是涉及到私有封装的概念,而私有封装是面向对象设计概念中重要的基石之一


“需要指向类外部的东西是由于有缺陷的程序设计。”我强烈不同意。 - J.N.
1
你真的是想说任何使用图形的程序都设计得很差吗?使用指针进行导航也是设计不良吗?我会认为几乎相反:如果你在类内分配了某些东西,将对象本身作为成员通常更合适。指针应该保留给在类外分配的东西。 - James Kanze
@JamesKanze 什么是“图形”?虽然我认为你指的是典型的ADT称为“图形”。对于这个例子,图形的所有节点(顶点)应该在图形类中分配。如果将节点类声明为图形的私有子类,则节点类可以公开指向图形类的指针。用户不应该关心原始指针,他们应该通过公共成员函数浏览图形。 - Lundin
@JamesKanze 调用者期望有像next()、previous()、up()、down()或其他的函数。但是调用者为什么要关心对象分配的地址呢?举个现实中的例子,我写了一个链表类。节点对象有“next”和“prev”指针,这些指针是公开的,但是节点类是链表的私有类。公共成员函数将具有“add”、“remove”、“find”、“change”、“traverse”等名称。因此,调用者无需在对象之间导航。事实上,调用者对类的实现方式并不关心。 - Lundin
@J.N. 多有趣啊。你的主观意见,没有提供任何理性的论据,对社区来说是非常有趣和有益的。 - Lundin
显示剩余10条评论

0

要使用哪一个取决于你需要什么。

例如,如果你需要某种依赖注入,可以使用引用成员变量。即使如此,你也可以使用指针。但是请记住,具有引用成员的类通常应该是不可复制的。

在大多数情况下,你应该使用指针或值成员变量。


2
引用使对象不可分配,但仍然可以复制。(但我同意你的基本观点:在类类型中,大多数情况下更喜欢使用指针而不是引用。除非该类型已经是不可复制的。) - James Kanze
@JamesKanze 是的。说得好。我对于不可复制的想法是,该类继承自boost::noncopyable。在这种情况下,它也是不可分配的。但你明白我的意思了。 - BЈовић

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接