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

时间:2018-02-07 20:51:21

标签: c++ class pointers dynamic-memory-allocation static-memory-allocation

可能这个问题已经被问过,但我找不到了。如果你看到了什么,请重定向我。 问题: 使用有什么好处:

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 !!!”。那么我为什么要使用“new”关键字?

1 个答案:

答案 0 :(得分:3)

  

我知道第一个选项在堆栈上分配空间   使指针指向它,而第二个指定空间   堆并使指针指向它。

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

特别是,这个代码似乎只是纯粹的盲目运气&#34;工作&#34;在所有:

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

...上面的代码正在调用未定义的行为,并且在理想的世界中它会简单地崩溃,因为您在无效指针上调用方法。但是C ++编译器通常更喜欢最大限度地提高效率而不是优雅地处理程序员错误,所以他们通常不会检查无效指针,因为你的bark()方法实际上并没有使用来自Dog对象,它可以在没有任何明显崩溃的情况下执行。尝试使用bark()方法虚拟,OTOH,您可能会看到上述代码崩溃。

  

第二个在堆上分配一个空格并使指针指向   它

这是正确的。

  

但我也读到第二种选择是乏味的,因为你必须这样做   用delete删除空格。

不仅单调乏味,而且容易出错 - 很容易(在一个非平凡的程序中)最终得到一个忘记调用delete的代码路径,然后就会出现内存泄漏。或者,您可能最终在同一指针上调用delete两次,然后您有未定义的行为,可能会崩溃或数据损坏。这两个错误都不是很有趣的调试。

  

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

传统上,当您需要对象保持有效的时间超过调用代码的范围时,您将使用动态分配 - 例如,如果您需要对象即使在创建对象的函数之后仍然存在在已经返回。与堆栈分配对比:

myClass someStackObject;

...其中someStackObject保证在调用函数返回时被销毁,这通常是一件好事 - 但是如果你需要someStackObject在你的函数之后仍然存在已经回来了。

现在,大多数人会完全避免使用原始/ C风格的指针,因为它们非常容易出错。在堆上分配对象的现代C ++方法如下所示:

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

...这是首选,因为它为你提供了一个堆分配的myClass对象,只要至少有一个指向它的std :: shared_ptr(好),它的指向对象将继续存在,但是当没有std :: shared_ptr指向它时,也会自动删除(更好,因为这意味着没有内存泄漏,也不需要显式调用delete,这意味着没有潜在的双重 - 删除)