繁体   English   中英

c++:何时使用指针?

[英]c++: when to use pointers?

在阅读了一些教程后,我得出结论,应该始终使用指针来表示对象。 但是我在阅读一些 QT 教程( http://zetcode.com/gui/qt4/painting/ )时也看到了一些例外情况,其中 QPaint ZA8CFDE6331BD59EB2AC966F8911C4B6 上创建了堆栈。 所以现在我很困惑。 什么时候应该使用指针?

如果您不知道何时应该使用指针,请不要使用它们。

很明显,当您需要使用它们时,每种情况都不同。 何时应该使用它们并不容易简明总结。 不要养成“总是使用对象指针”的习惯,这肯定是个坏建议。

使用指针的主要原因:

  1. 控制 object 寿命;
  2. 不能使用引用(例如,您想在向量中存储不可复制的内容);
  3. 您应该将指针传递给第三方 function;
  4. 也许是一些优化原因,但我不确定。

我不清楚您的问题是ptr-to-obj vs stack-based-obj还是ptr-to-obj vs reference-to-obj。 还有一些用途不属于任何一类。

关于 vs stack,上面似乎已经介绍过了。 几个原因,最明显的是 object 的使用寿命。

关于 vs 引用,总是尽量使用引用,但是有些事情你只能用 ptrs 来做,例如(有很多用途):

  • 遍历数组中的元素(例如,遍历标准数组 [])
  • 当被调用的 function 分配一些东西并通过 ptr 返回它时

最重要的是,指针(和引用,与自动/基于堆栈和 static 对象相反)支持多态性。 指向基础 class 的指针实际上可能指向派生的 class。 这是 C++ 中支持的 OO 行为的基础。

首先,问题是错误的:困境不在指针和堆栈之间,而是在堆和堆栈之间。 您可以在堆栈上有一个 object 并将指针传递给该 object。 我假设您真正要问的是您是否应该声明指向 class 或 class 实例的指针。

答案是这取决于你想用 object 做什么。 如果 object 在控制离开 function 后必须存在,那么您必须使用指针并在堆上创建 object。 You will do this, for example, when your function has to return the pointer to the created object or add the object to a list that was created before calling your function.

另一方面,如果对象是 function 的本地对象,那么最好在堆栈上使用它。 这使编译器能够在控件离开 function 时调用析构函数。

那会是哪些教程? 实际上,规则是只有在绝对必要时才应该使用指针,这种情况很少见。 您需要阅读一本关于 C++ 的好书,例如 Koenig & Moo 的Accelerated C++

编辑:澄清一下-您不会使用指针的两个实例(此处使用字符串作为示例-对于任何其他类型的 go 相同):

class Person {
   public:
      string name;       // NOT string * name;
   ...
};


void f() {
   string value;        // NOT string * value
   // use vvalue
}

您通常必须在以下情况下使用指针:

  1. 您需要属于不同类的对象集合(在大多数情况下,它们将具有共同的基础)。

  2. 您需要一个堆栈分配的对象集合,该集合非常大,可能会导致堆栈溢出。

  3. 您需要一种可以快速重新排列对象的数据结构——如链表、树等。

  4. 您的 object 需要一些复杂的生命周期管理逻辑。

  5. 您需要一个允许从 object 直接导航到 object 的数据结构——如链表、树或任何其他图形。

除了其他人提出的观点(特别是 w.r.t. 控制 object 的生命周期),如果您需要处理 NULL 对象,您应该使用指针,而不是引用。 可以通过类型转换创建 NULL 引用,但这通常不是一个好主意。

如果可能,永远不要使用指针。 依靠引用传递,或者如果你要返回一个结构或 class,假设你的编译器有返回值优化。 (但是,您必须避免有条件地构造返回的 class)。

Java 没有指针是有原因的。 C++ 也不需要它们。 如果您避免使用它们,您将在 object 离开 scope 时获得自动 object 销毁的额外好处。 否则,您的代码将生成各种类型的 memory 错误。 Memory 泄漏可能非常棘手,并且由于未处理的异常而经常发生在 C++ 中。

如果必须使用指针,请考虑一些智能指针类,例如 auto_ptr。 对象的自动销毁不仅仅是释放底层的 memory。 有一个概念叫做 RAII。 一些对象需要额外处理销毁。 例如互斥锁和关闭文件等。

通常在以下情况下使用对象的指针/引用:

  • 将它们传递给其他方法

  • 创建一个大数组(我不确定正常的堆栈大小是多少)

在以下情况下使用堆栈:

  • 您正在创建一个 object,它在该方法中生存和死亡

  • object 是 CPU 寄存器的大小或更小

我实际上在这种情况下使用指针:

class Foo
{
    Bar* bar;

    Foo(Bar& bar) : bar(&bar) { }

    Bar& Bar() const { return *bar; }
};

在此之前,我使用了从构造函数初始化的引用成员,但是编译器在创建复制构造函数、赋值运算符等时遇到了问题。

戴夫

使用指针与两个正交的事物有关:

  1. 动态分配 通常,您应该动态分配,当 object 的寿命要长于创建它的 scope 时。 这样的 object 是必须明确指定所有者的资源(最常见的是某种智能指针)。

  2. 按地址访问(不管 object 是如何创建的)。 在这种情况下,指针并不意味着所有权。 在以下情况下可能需要此类访问:

    • 一些已经存在的界面需要这样。
    • 应该建模可能是 null 的关联。
    • 应该避免复制大对象,否则根本不可能复制,但不能使用引用(例如,stl 集合)。

#1 和 #2 可以出现在不同的配置中,例如,您可以想象通过指针访问动态分配的 object,但是这样的 object 也可以通过引用某些 function 来传递。 您还可以获得指向在堆栈上创建的一些 object 等的指针。

使用表现良好的可复制对象传递值是大量代码的 go 的方式。

如果速度真的很重要,请尽可能使用按引用传递,最后使用指针。

当您不想在堆栈帧被清空时破坏 object 时,请使用指针。

尽可能使用引用传递参数。

说到 C++,当程序离开创建它的 scope 时,在堆栈上创建的对象不能使用。所以一般来说,当你知道你不需要一个超过 ZC1C425268E68385D14AB5074C17A9 的变量时,你可以创建它在堆栈上。

具体来说说Qt,Qt通过处理很多堆对象的memory管理来帮助程序员。 对于从QObject派生的对象(几乎所有以“ Q ”为前缀的类都是),构造函数采用可选参数 parent。 然后父级拥有 object,当父级被删除时,所有拥有的对象也被删除。 本质上,子代的销毁责任就交给了父代object。 使用这种机制时,必须在堆上创建子QObject

简而言之,在 Qt 中,您可以轻松地在堆上创建对象,并且只要设置适当的父级,您只需担心破坏父级。 但是,通常 C++ 需要记住销毁堆对象或使用智能指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM