我习惯于使用Java进行编程,在Java中你几乎不需要考虑指针。但目前我正在写C++程序。在创建包含其他类成员的类时,何时应该使用指针,何时不应该使用?例如,什么时候会想要这样做:
class Foo {
Bar b;
}
与此相反:
class Foo {
Bar* b;
}
避免使用指针。
以下情况下可以使用它们:
Bar
实例实际上由程序的其他部分管理,而 Foo
类只需要能够访问它。Bar
对象(也就是说,你希望在构造 Foo
之后创建它)。Bar
对象可能根本不存在;在 Java 中,你将使用 null
。但是,还可以看看boost::optional。Bar
实际上是一个基类,而且你需要该实例是多态的。在任何这些情况 (*)下,从使用智能指针开始,例如 boost::shared_ptr。否则,你很可能会忘记释放内存,迟早会出问题。一旦你知道你在做什么,请逐案考虑什么类型的指针最好。
(*) 任何情况 - 除了可能与 GUI 小部件相关的项目;在这种情况下,你的工具包很可能也会为你管理资源。
class Foo {
Bar b;
}
b被包含在Foo中。如果Foo对象结束生命周期,b也会自动结束生命周期。这就是组合的模型。上面的b表示对象本身,而不仅仅是像Java中的指针。因此,如果b超出作用域,对象也将结束生命周期。
class Foo {
Bar * b;
}
这里,对象b指向的是Foo对象使用或引用的内容。如果Foo对象结束其生命周期,b指向的对象可能会继续存在,具体取决于情况。这可以用来模拟聚合和一般关系。例如,该对象可以与其他Foo对象共享。
指针在C++中与Java中的引用类似。它们也可以指向空值。如果一个指针指向空值,则称为空指针。
与指针类似的是引用。在C++中,引用必须被初始化,并且只能指向一个(有效的)对象,对于该引用被初始化时所指的对象而言。因此,引用不能持有可表示“空值”的值,如Java中的null
。
Foo
对象结束生命周期,b自动结束生命周期”,而不是在Foo
的位置上使用Bar
。 - His在第一个例子中,当你构造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。
对于较小的对象来说,这是很危险的,因为你可能会忘记分配内存。
new
返回一个指针,而不是一个值。你是想用 Foo foo; 还是 Foo foo = Foo(); 代替? - strager在不同的情况下,两者都可以。例如,如果您知道如何在构造类Foo的对象时构造b,则第一种方法是可行的。但是,如果您不知道,唯一的选择就是使用第二种方法。