为什么要使用指针而不是对象本身?

变化:

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

Object *myObject = new Object;

而不是:

Object myObject;

或者,而不是使用函数testFunc(),像这样

myObject.testFunc();

我们必须写:

myObject->testFunc();

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

约瑟夫·曼斯菲尔德:

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

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

重要的提示是您应始终使用适当的工具进行作业在几乎所有情况下,都比执行手动动态分配和/或使用原始指针更合适,更安全。

动态分配

在您的问题中,您演示了两种创建对象的方法。主要区别是对象的存储时间。Object myObject;块中执行操作时,将创建具有自动存储持续时间的对象,这意味着当对象超出范围时将被自动销毁。执行此操作时new Object(),该对象具有动态存储持续时间,这意味着该对象将保持活动状态,直到您明确delete其保留为止您仅应在需要时使用动态存储期限。也就是说,您应该始终喜欢在可以时创建具有自动存储持续时间的对象

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

  1. 您需要对象超出当前作用域的范围 -该特定对象位于该特定内存位置,而不是其副本。如果您可以复制/移动对象(大多数情况下应该如此),则应该使用自动对象。
  2. 您需要分配大量内存,这很容易填满堆栈。如果我们不必为此担心(大多数时候您不必如此),那将是很好的,因为这确实超出了C ++的范围,但是不幸的是,我们必须处理系统的实际情况。我们正在开发。

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

指针

但是,除动态分配外,原始指针还有其他更通用的用法,但大多数都有您应首选的替代方法。和以前一样,除非您确实需要使用指针,否则请始终选择替代方法

  1. 您需要参考语义有时,您想要使用指针传递对象(无论如何分配),因为您希望传递给它的函数可以访问该特定对象(而不是其副本)。但是,在大多数情况下,您应该更喜欢引用类型而不是指针,因为这是专门为它们设计的。请注意,这不一定是要延长对象的生存期,使其超出当前范围,如上述情况1所示。和以前一样,如果您可以传递对象的副本,则不需要引用语义。

  2. 您需要多态性您只能通过指向对象的指针或引用来多态调用函数(即,根据对象的动态类型)。如果这是您需要的行为,则需要使用指针或引用。同样,引用应该是首选。

  3. 您想通过允许nullptr在省略对象时传递来表示该对象是可选如果是参数,则应该首选使用默认参数或函数重载。否则,您最好使用一种封装此行为的类型,例如std::optional(在C ++ 17中引入-使用较早的C ++标准,请使用boost::optional)。

  4. 您希望解耦编译单元以缩短编译时间指针的有用属性是您只需要指向类型的前向声明(要实际使用该对象,您需要一个定义)。这样,您就可以使编译过程的各个部分脱钩,从而可以大大缩短编译时间。请参阅“ Pimpl习惯用法”

  5. 您需要与C库或C样式库接口。在这一点上,您不得不使用原始指针。最好的办法是确保在最后可能的时候只松开原始指针。您可以从智能指针中获取原始指针,例如,通过使用其get成员函数。如果库为您执行了一些分配,希望您可以通过句柄对其进行分配,则通常可以使用自定义删除程序将句柄包装在智能指针中,该删除器将适当地分配对象。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么要使用ClassCastException而不是编译错误?

为什么要使用Optional.of而不是Optional.ofNullable?

为什么要使用责任链而不是简单的for循环?

为什么要使用uImage而不是zImage

为什么要使用jQuery on()而不是click()

为什么要使用IHttpActionResult而不是HttpResponseMessage?

为什么要使用双重间接?或为什么使用指向指针的指针?

为什么要使用var而不是类型?

为什么要使用Runnable而不是Thread?

为什么要使页面对象实例化而不是静态?

为什么要使用null!=而不是任何东西!= null?

为什么要使用.toString(32)而不是.toString(36)?

为什么要使用工厂而不是“新工厂”?

为什么CreateWindow()函数需要WindowClass的名称成员而不是指向类本身的指针?

为什么Clang会警告未使用的指针和未使用的原语,而不是未使用的对象?

为什么要使用beforeRouteEnter而不是挂载?

为什么我要使用异步而不是非异步方法

为什么要使用“ int input {0};” 而不是“ int intput”;

为什么要使用移位而不是for循环?

为什么要使用Char而不是String?

创建带有关联指针的对象时,为什么要使用“ new”?

为什么要使用指针?

为什么要使用fillRect而不是translation?

为什么要使用__stdcall作为函数指针

为什么要使用资源而不是路由?

为什么要使用block \ grid而不是for循环?

为什么要使用isinstance()而不是type()?

为什么允许结构本身具有“指向其自身类型的指针”而不是成员“结构类型(的数组)”本身?

为什么要使用字符指针的大小