何时使用指针而何时不使用?
我习惯于做Java编程,在编程时你永远不必考虑指针。 但是,目前我正在用C ++编写程序。 在创建具有其他类成员的类时,我应该何时使用指针,何时不应该使用指针? 例如,我什么时候想要这样做:
class Foo { Bar b; }
与此相反:
class Foo { Bar* b; }
首先避免使用指针。
在以下情况下使
- 你想使用Pimpl习语或抽象工厂 。
-
Bar
实例实际上是由程序的其他部分管理的,而Foo
类只需要能够访问它。 - 你想推迟
Bar
对象的构造(即,你想在构造Foo
之后创建它)。 - 在您的业务逻辑中,
Bar
对象可能根本不存在; 你也会在Java中使用null
。 但是,请查看boost :: optional 。 -
Bar
实际上是一个基类,你需要实例是多态的。 - 您碰巧使用的工具包更喜欢将GUI小部件作为指针。 示例可以包括(但不限于) wxWidgets和GLUI 。
在任何这些情况下(*),首先使用智能指针,例如boost :: shared_ptr 。 否则,您可能迟早会忘记释放内存。 一旦你知道自己在做什么,就要考虑具体的指针类型。
(*)任何情况 – 除了可能是关于GUI小部件的子弹; 在这种情况下,您的工具包很可能也会为您管理资源
class Foo { Bar b; }
b 包含在Foo中。 如果Foo对象结束生命周期,b也会自动结束生命周期。 这是什么模型组成。 上面的b表示对象本身,而不是像Java中那样指向它的指针。 因此,如果b超出范围,该对象将终止生命周期。
class Foo { Bar * b; }
这里,对象b指向的对象由 Foo对象使用或由 Foo对象引用 。 如果Foo对象结束生命周期,则对象b指向的可以继续生存,具体取决于具体情况。 这可以用于模拟聚合和一般关系。 例如,该对象可以与其他Foo对象共享。
指针大致是Java中的引用。 他们也可以指出一切。 如果指针指向什么,则它是空指针。
与指针类似的是引用。 必须初始化C ++中的引用,并且只能指向初始化引用的一个(有效)对象。 因此,对它的引用不能保持在Java中可能意味着“无”的null
。
在第一个示例中,在构造Foo对象时,将自动分配Bar对象的内存。 在第二种情况下,您需要自己分配内存。 所以你必须打电话:
Foo *foo = new Foo(); foo->b = new Bar();
如果Bar对象很大并且您不想将其与Foo对象捆绑在一起,则可能需要这样做。 当Bar对象的构造独立于Foo对象的创建时,也是可取的。 在这种情况下,b对象被“注入”到foo中:
Foo *foo = new Foo(); foo->b = b_ptr;
其中b_ptr在其他地方构造,指针传递给foo。
对于较小的物体,这是危险的,因为您可能忘记分配内存。
在不同条件下两者都可以。 例如,如果您知道在构造类Foo的对象时如何构造b,则第一个是OK。 但如果你不这样做,唯一的选择是使用秒。
您需要进行一些汇编编程并很好地理解内存布局。 与Java或其他语言不同,C只是一个跨平台程序集。 要正确使用它,应该了解低级细节。
所有评论都是有效的,但是对于像你这样从高级语言跳到C语言的人来说,拥有这种经验将是非常有益的。 通过正确的理解,你不会再问这样的问题了。