Java 何时使用指针,何时不使用?

Java 何时使用指针,何时不使用?,java,c++,pointers,Java,C++,Pointers,我习惯于做Java编程,在编程时你永远不需要考虑指针。但是,此刻我正在用C++编写一个程序。在创建包含其他类的成员的类时,何时应该使用指针,何时不应该使用指针?例如,我希望在何时执行此操作: class Foo { Bar b; } 与此相反: class Foo { Bar* b; } 在不同的条件下,两者都可以。例如,如果您知道如何在构造Foo类的对象时构造b,那么第一个就可以了。但如果你不这样做,唯一的选择就是使用第二个 从避免指针开始 在下列情况下使用它们: 您要使

我习惯于做Java编程,在编程时你永远不需要考虑指针。但是,此刻我正在用C++编写一个程序。在创建包含其他类的成员的类时,何时应该使用指针,何时不应该使用指针?例如,我希望在何时执行此操作:

class Foo {
    Bar b;
}
与此相反:

class Foo {
    Bar* b;
}

在不同的条件下,两者都可以。例如,如果您知道如何在构造Foo类的对象时构造b,那么第一个就可以了。但如果你不这样做,唯一的选择就是使用第二个

从避免指针开始

在下列情况下使用它们:

  • 您要使用,或
  • Bar
    实例实际上由程序的其他部分管理,而
    Foo
    类只需要能够访问它
  • 您想推迟构建
    对象(即,您想在构建
    Foo
    之后创建它)
  • 在您的业务逻辑中,
    Bar
    对象可能根本不存在;您也可以在Java中使用
    null
    。不过,也要检查一下
  • Bar
    实际上是一个基类,您需要实例是多态的
  • 您碰巧使用了一个更喜欢将GUI小部件作为指针呈现的工具包。示例包括(但不限于)和
在任何一种情况下(*),首先使用智能指针,例如。否则,您迟早会忘记释放内存。一旦你知道自己在做什么,就要逐个地考虑指针类型是什么。
(*)任何情况下–可能除了关于GUI小部件的项目符号;在这种情况下,您的工具包很可能也会为您管理资源

在第一个示例中,当您构建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

对于较小的对象,这是危险的,因为您可能会忘记分配内存

class Foo {
    Bar b;
}
b包含在Foo中。如果Foo对象结束生存期,b也会自动结束生存期。这就是模型的组成。上面的b表示对象本身,而不是像Java中那样指向它的指针。因此,如果b超出范围,对象将结束生存期

class Foo {
    Bar * b;
}
这里,指向的对象b由Foo对象使用或引用。如果Foo对象结束了生存期,那么b指向的对象可能会继续生存,具体取决于环境。这可用于建模聚合和一般关系。例如,该对象可以与其他Foo对象共享

指针与Java中的引用大致相同。它们也不能指向任何东西。如果指针不指向任何内容,则为空指针


与指针类似的是引用。C++中的引用必须初始化,只能指向一个(有效)对象,对象被初始化。因此,引用不能包含与Java中的
null
类似的“无”值。

您需要进行一些汇编编程,并充分了解内存布局。与Java或其他语言不同,C只是一个跨平台程序集。为了正确地使用它,人们应该了解底层细节


所有的评论都是有效的,但是对于像你这样从高级语言跳转到C语言的人来说,拥有这样的经验是非常有益的。如果理解得当,您就不会再问这样的问题。

new
返回指针,而不是值。你是说福福;或Foo-Foo=Foo();相反?…或者在您编写工具包的情况下(这通常是我的情况)。我从来没有遇到过智能指针可以解决的指针问题,所以我不会说“使用它们!”而是“在大多数情况下使用它们是最容易的。”也许我是一个人。但我认为,尤其是初学者(当然不是在现实项目中)应该首先尝试使用原始指针。我认为这类似于“IDE/no IDE”问题。他们应该知道为什么智能指针是有用的,在使用智能指针神奇地避免别人告诉他们的问题之前,他们会避免什么陷阱。@litb:我同意你的观点。我想如果你问现实世界项目的最佳实践(这是我回答的问题),或者学习理解基本的东西,答案可能会有点不同。Otoh,我想他已经知道如何在基本的情况下使用原始指针。起点应该是::SCONDEX-PTR,只在需要这个功能时去SyfdtPtR。注意问题是C++,而不是C。但是NOBOS不知道C++和C.的区别,这仍然是一个很好的建议。这可能为时已晚。但是在第一段中,你不应该说“如果
Foo
对象结束生命周期,b也会自动结束生命周期。”而不是用
Bar
代替
Foo