为什么我应该使用指针而不是对象本身?

我来自java背景,已经开始使用C++中的对象。但我想到的一件事是,人们经常使用指向对象的指针,而不是对象本身,例如以下声明:

对象*myObject=新对象;

而不是:

对象myObject;

或者不使用函数,比如说testFunc(),如下所示:

myObject.testFunc();

我们必须写:

myObject->testFunc();

但我不明白我们为什么要这样做。我认为这与效率和速度有关,因为我们可以直接访问内存地址。我说得对吗

非常不幸的是,您经常看到动态分配。这就说明了有多少C++程序员是坏的。

从某种意义上说,你有两个问题捆绑在一起。第一个问题是什么时候应该使用动态分配(使用new)?第二个问题是什么时候应该使用指针

重要的带回家的信息是,您应该始终为作业使用适当的工具。在几乎所有情况下,都有比执行手动动态分配和/或使用原始指针更合适、更安全的方法

动态分配

在您的问题中,您已经演示了创建对象的两种方法。主要区别在于对象的存储持续时间。执行对象myObject时在一个块中,对象是以自动存储持续时间创建的,这意味着当对象超出范围时,它将自动销毁。执行new Object()时,对象具有动态存储持续时间,这意味着在您显式地删除它之前,它一直处于活动状态。您应该仅在需要时使用动态存储持续时间。
也就是说,如果可以的话,您应该始终更喜欢创建具有自动存储持续时间的对象

您可能需要动态分配的两种主要情况:

  1. 您需要对象在当前作用域之外生存-特定内存位置的特定对象,而不是它的副本。如果您可以复制/移动对象(大多数情况下您应该可以),那么您应该选择自动对象
  2. 您需要分配大量内存,这可能很容易填满堆栈。如果我们不必担心这(这是大多数时候你不需要),那将是很好的,因为它实际上是在C++的权限之外,但是不幸的是,我们必须处理我们正在开发的系统的实际情况。

当您确实需要动态分配时,应该将其封装在智能指针或其他执行RAII的类型(如标准容器)中。智能指针提供动态分配对象的所有权语义。例如,看一下std::unique\u ptrstd::shared\u ptr。如果使用得当,几乎可以完全避免执行自己的内存管理(请参见零规则)

指针

然而,除了动态分配之外,原始指针还有其他更一般的用途,但大多数都有您更喜欢的替代方法。与以前一样,除非您真的需要指针,否则总是更喜欢备选方案

  1. 您需要引用语义。有时,您希望使用指针传递对象(不管它是如何分配的),因为您希望传递对象的函数能够访问该特定对象(而不是它的副本)。然而,在大多数情况下,您应该更喜欢引用类型而不是指针,因为这正是它们的设计目的。注意,这不一定是关于将对象的生存期扩展到当前范围之外,如上面的情况1所示。如前所述,如果可以传递对象的副本,则不需要引用语义

  2. 您需要多态性。只能通过对象的指针或引用以多态方式(即,根据对象的动态类型)调用函数。如果这是您需要的行为,那么您需要使用指针或引用。同样,应首选参考文献

  3. 您希望通过在省略对象时允许传递nullptr来表示对象是可选的。如果它是一个参数,您应该更喜欢使用默认参数或函数重载。否则,您最好使用一种封装这种行为的类型,如 STD::可选 >(在C++ 17中引入-使用较早的C++标准,使用 Boo::可选)。

  4. 您希望解耦编译单元以缩短编译时间。指针的有用特性是只需要指向类型的前向声明(要实际使用对象,需要定义)。这允许您分离编译过程的各个部分,这可能会显著缩短编译时间。参见Pimpl成语

  5. 您需要与C库或C样式库接口。此时,您必须使用原始指针。你能做的最好的事情就是确保你只在最后一刻才放开你的原始指针。例如,可以使用智能指针的get成员函数从智能指针获取原始指针。如果库为您执行某个分配,它希望您通过句柄释放该分配,您通常可以使用自定义删除器将句柄包装在智能指针中,该删除器将适当地释放对象

发表评论