在堆上分配指针的原因是什么?

What are the reasons to allocate a pointer on the heap?

本文关键字:是什么 指针 分配      更新时间:2023-10-16

可能已经问了这个问题,但我找不到它。如果您看到了一些东西,请重定向我。问题:使用的好处是什么:

myClass* pointer;

超过

myClass* pointer = new(myClass);

从阅读其他主题中,我了解第一个选项将在堆栈上分配一个空间,并使指针指向它,而第二个则在堆上分配空间并指向指针。但是我还读到,第二个选项是乏味的,因为您必须用删除对空间进行处理。那么,为什么要使用第二种选项。我有点菜鸟,所以请详细解释。

编辑

#include <iostream>
using namespace std;
class Dog
{
        public:
                void bark()
                {
                        cout << "wouf!!!" << endl;
                }
};

int main()
{
        Dog* myDog = new(Dog);
        myDog->bark();
        delete myDog;
        return 0;
}

#include <iostream>
using namespace std;
class Dog
{
        public:
                void bark()
                {
                        cout << "wouf!!!" << endl;
                }
};

int main()
{
        Dog* myDog;
        myDog->bark();
        return 0;
}

既编译并给我" Wouf !!!"。那么为什么我要使用"新"关键字?

我了解,第一个选项是在堆栈上分配空间的在第二个分配空间上的时候,指针指向它堆并指向它。

上面是不正确的 - 第一个选项为指针本身在堆栈上的指针本身分配空格,但并未分配任何对象的空间,以指向指针。也就是说,指针并没有指向任何特别的东西,因此使用没有用(除非/直到设置指针指向某物(

(

特别是,这个代码似乎是"工作"是纯粹的盲目运气。完全:

Dog* myDog;
myDog->bark();   // ERROR, calls a method on an invalid pointer!

...上面的代码正在调用不确定的行为,在理想的世界中,它将崩溃,因为您在无效的指针上调用方法。但是C 编译器通常更喜欢最大化效率,而不是优雅地处理程序员错误,因此通常不会对无效的销售支票进行检查,并且由于您的bark()方法实际上没有使用Dog对象中的任何数据,因此可以执行没有任何明显的崩溃。尝试制作bark()方法虚拟,OTOH,您可能会看到上面代码的崩溃。

第二个分配空间在堆上,并指向指向它。

那是正确的。

,但我还读到第二种选择很乏味,因为您必须用删除分配空间。

不仅乏味,而且容易出错,而且很容易(在非平凡的程序中(最终获得代码路径,您忘了调用删除,然后您会有内存泄漏。或者,或者,您最终可能会在同一指针上调用两次删除,然后您的行为不确定,可能崩溃或数据损坏。调试都不是很有趣。

那么为什么要使用第二种选项。

传统上,当您需要对象保持有效的时间比调用代码的范围更长时,您会使用动态分配 - 例如,即使在创建对象的功能之后,您需要对象粘附回。与堆栈分配形成对比:

myClass someStackObject;

...当调用函数返回时,保证someStackObject被销毁,这通常是一件好事 - 但如果您需要someStackObject即使您的函数返回,则不是一件好事。

这些天,大多数人会完全避免使用原始/C风格的指针,因为它们是如此危险的错误。分配堆对象的现代C 看起来像这样:

std::shared_ptr<myClass> pointer = std::make_shared<myClass>();

...这是首选但是,在没有std :: shared_ptr指向的那一刻时,也会自动删除(甚至更好,因为这意味着没有内存泄漏,也无需明确调用delete,这意味着没有潜在的双骨骼(

相关文章: