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

标签 c++ pointers c++11

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

Object *myObject = new Object;


而不是:

Object myObject;


或者代替使用函数,让我们说testFunc(),如下所示:

myObject.testFunc();


我们必须写:

myObject->testFunc();


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

最佳答案

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

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

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

动态分配

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

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


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


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

指针

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


您需要参考语义。有时您想要使用指针传递对象(无论如何分配),因为您希望传递给它的函数可以访问该特定对象(而不是其副本)。但是,在大多数情况下,您应该更喜欢引用类型而不是指针,因为这是专门为它们设计的。请注意,这不一定是要延长对象的生存期,使其超出当前范围,如上述情况1所示。和以前一样,如果您可以传递对象的副本,则不需要引用语义。
您需要多态性。您只能通过指针或对对象的引用来多态调用函数(即,根据对象的动态类型)。如果这是您需要的行为,则需要使用指针或引用。同样,引用应该是首选。
您想通过允许在省略对象时传递nullptr来表示该对象是可选的。如果是参数,则应该首选使用默认参数或函数重载。否则,您最好使用一种封装这种行为的类型,例如std::optional(在C ++ 17中引入-使用较早的C ++标准,请使用boost::optional)。
您希望解耦编译单元以缩短编译时间。指针的有用属性是,您只需要指向类型的前向声明(要实际使用该对象,您需要一个定义)。这使您可以使编译过程的各个部分脱钩,从而可以显着缩短编译时间。请参见Pimpl idiom
您需要与C库或C样式库接口。在这一点上,您不得不使用原始指针。最好的办法是确保在最后可能的时候只松开原始指针。您可以从智能指针中获取原始指针,例如,通过使用其get成员函数。如果库为您执行了一些分配,希望您可以通过句柄进行分配,则通常可以使用自定义删除程序将句柄包装在智能指针中,该删除器将适当地分配对象。

关于c++ - 为什么要使用指针而不是对象本身?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33904436/

相关文章:

c++ - 在线程之间共享类

c - 指针指向不同的数据类型

c++ - 如何确定 'auto' 变量的实际类型

c++ - 如何将 std::set_intersection 用于 2 个不同但相关的类型并输出到另一种类型

c++ - call .mutable_mynested msg() 和 .nested msg() 之间有什么区别吗?

c++ - WTL Error : RegisterClassObjects(DWORD, DWORD) throw()' 已经有一个正文

c++ - 在 Eclipse CDT 中使用运算符 [] 的 vector vector 中未解析 "size"

c - 结构中的变量声明问题

c++ - 如果未明确说明大小信息,模板函数如何知道大小?

c++ - 插入或 push_back 到 std::vector 的末尾?