我如何决定是使用指针还是常规变量

How do I decide if I should use a pointer or a regular variable?

本文关键字:指针 变量 常规 何决定 决定      更新时间:2023-10-16

在c++中,我可以将一个字段声明为某种类型的常规变量,在构造函数中实例化它,然后再使用它:

private:    Foo field;
...
A::A() {
    // upd: likely i instatiate field wrong ways (see comments)
    field = FieldImpl();
}
....
method(field);

或者我也可以使用指针:

private:    Foo* field;
...
A::A() {
    field = new FieldImpl();
}
A::~A() {
    delete field;
}
...
method(*field);

在声明字段时,如何决定应该使用指针还是常规变量?

如果:

  • 被引用的对象可以比父对象存活时间长。
  • 由于大小的原因,您希望确保引用的对象在堆上。
  • 指针是从类外部提供的。
  • Null是可能的值
  • 该字段可以动态设置为不同的对象。
  • 实际的对象类型在运行时确定。例如,该字段可以是一个基类指针,指向多个子类中的任何一个。

你也可以使用智能指针。

上面的最后一点适用于示例代码。如果你的字段是Foo类型的,并且你给它分配了一个FieldImpl,剩下的就是FieldImpl的Foo部分。这被称为切片问题。

常规变量 if

  • Foo是类不可分割的一部分,即每个实例总是有自己的Foo
  • Foo不是太大(它可以放在堆栈上)。
<

指针/strong>如果

  • 多个实例可以共享单个Foo
  • 在某些情况下可能没有Foo
  • Foo真的很大,应该一直在堆上。

c++在设计时就考虑了自动变量。像RAII这样关键的c++习惯用法依赖于自动变量。由于c++的设计决策,使用自动变量比使用指针更简单、更容易。除非确实需要指针提供的功能,否则不应该增加使用指针的复杂性。(如果你必须使用智能指针)

复杂性需要被证明是合理的,在这个例子中,你没有说明指针例子中额外复杂性的任何原因,所以你应该使用一个自动变量。

在使用了10年的c#和Java之后,指针很简单,而常规变量对我来说很复杂:)所以应该有更严重的理由不使用指针。例如,我猜指针不是处理器缓存友好的

c#和Java的设计与c++不同。它们的语法和运行时旨在使指针成为更简单的(或唯一的)方法,并且它们会处理在幕后为您创建的一些问题。试图绕过语言来避免Java和c#中的指针会增加复杂性。

此外,c#和Java在很大程度上依赖于多态类型,并且它们没有c++所具有的"不为不使用的东西付费"的策略。多态类型需要指针,但c#和Java很乐意让你付出代价,即使你不需要,而c++不这样做。