在堆上分配指针的原因是什么?
What are the reasons to allocate a pointer on the heap?
可能这个问题已经有人问过,但我找不到。如果你看到了什么,请重定向我。
问题:
使用 :
有什么好处
myClass* pointer;
超过
myClass* pointer = new(myClass);
通过阅读其他主题,我了解到第一个选项在堆栈上分配一个 space 并使指针指向它,而第二个选项在堆上分配一个 space 并创建一个指针指向它。
但我还读到第二个选项很乏味,因为您必须使用 delete 解除分配 space。
那么为什么有人会使用第二种选择。
我有点菜鸟所以请详细解释。
编辑
#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" 关键字呢?
I understand that the first option allocates a space on the stack and
makes the pointer point to it while the second allocates a space on
the heap and make a pointer point to it.
上面是不正确的——第一个选项在堆栈上为指针本身分配space,但没有为任何分配space指针指向的对象。也就是说,指针没有指向任何特定的东西,因此没有用处(unless/until 你将指针设置为指向某物)
特别是,这段代码似乎“有效”纯粹是盲目的运气:
Dog* myDog;
myDog->bark(); // ERROR, calls a method on an invalid pointer!
... 上面的代码正在调用 未定义的行为 ,在理想情况下,它只会崩溃,因为您在无效指针上调用方法。但是 C++ 编译器通常更喜欢最大化效率而不是优雅地处理程序员错误,因此它们通常不会检查无效指针,并且由于您的 bark()
方法实际上不使用 [=14= 中的任何数据] 对象,它能够在没有任何明显崩溃的情况下执行。尝试将您的 bark()
方法设为虚拟方法,OTOH,您可能会看到上述代码发生崩溃。
the second allocates a space on the heap and make a pointer point to
it.
没错。
But I read also that the second option is tedious because you have to
deallocate the space with delete.
不仅乏味,而且容易出错 -- 很容易(在一个不平凡的程序中)以忘记调用 delete 的代码路径结束,然后发生内存泄漏。或者,您最终可能会在同一个指针上调用 delete 两次,然后您会出现未定义的行为,并且可能会崩溃或数据损坏。调试这两个错误都不是很有趣。
So why would one ever use the second option.
传统上,当您需要对象保持有效的时间超过调用代码的范围时,您会使用动态分配——例如,如果您需要对象在您创建对象的函数之后仍然存在在已经返回。将其与堆栈分配进行对比:
myClass someStackObject;
... 其中 someStackObject
保证在调用函数 returns 时被销毁,这通常是一件好事——但如果您需要 someStackObject
保留即使在您的函数返回后仍然存在。
如今,大多数人会完全避免使用 raw/C-style 指针,因为它们非常容易出错。在堆上分配对象的现代 C++ 方法如下所示:
std::shared_ptr<myClass> pointer = std::make_shared<myClass>();
... 这是首选,因为它为您提供了一个堆分配的 myClass 对象,只要至少有一个 std::shared_ptr 指向它(很好),但也将在没有 std::shared_ptr 指向它的那一刻自动删除(更好,因为这意味着没有内存泄漏并且不需要显式调用 delete
,这意味着没有潜在的双删除)
可能这个问题已经有人问过,但我找不到。如果你看到了什么,请重定向我。 问题: 使用 :
有什么好处myClass* pointer;
超过
myClass* pointer = new(myClass);
通过阅读其他主题,我了解到第一个选项在堆栈上分配一个 space 并使指针指向它,而第二个选项在堆上分配一个 space 并创建一个指针指向它。 但我还读到第二个选项很乏味,因为您必须使用 delete 解除分配 space。 那么为什么有人会使用第二种选择。 我有点菜鸟所以请详细解释。
编辑
#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" 关键字呢?
I understand that the first option allocates a space on the stack and makes the pointer point to it while the second allocates a space on the heap and make a pointer point to it.
上面是不正确的——第一个选项在堆栈上为指针本身分配space,但没有为任何分配space指针指向的对象。也就是说,指针没有指向任何特定的东西,因此没有用处(unless/until 你将指针设置为指向某物)
特别是,这段代码似乎“有效”纯粹是盲目的运气:
Dog* myDog;
myDog->bark(); // ERROR, calls a method on an invalid pointer!
... 上面的代码正在调用 未定义的行为 ,在理想情况下,它只会崩溃,因为您在无效指针上调用方法。但是 C++ 编译器通常更喜欢最大化效率而不是优雅地处理程序员错误,因此它们通常不会检查无效指针,并且由于您的 bark()
方法实际上不使用 [=14= 中的任何数据] 对象,它能够在没有任何明显崩溃的情况下执行。尝试将您的 bark()
方法设为虚拟方法,OTOH,您可能会看到上述代码发生崩溃。
the second allocates a space on the heap and make a pointer point to it.
没错。
But I read also that the second option is tedious because you have to deallocate the space with delete.
不仅乏味,而且容易出错 -- 很容易(在一个不平凡的程序中)以忘记调用 delete 的代码路径结束,然后发生内存泄漏。或者,您最终可能会在同一个指针上调用 delete 两次,然后您会出现未定义的行为,并且可能会崩溃或数据损坏。调试这两个错误都不是很有趣。
So why would one ever use the second option.
传统上,当您需要对象保持有效的时间超过调用代码的范围时,您会使用动态分配——例如,如果您需要对象在您创建对象的函数之后仍然存在在已经返回。将其与堆栈分配进行对比:
myClass someStackObject;
... 其中 someStackObject
保证在调用函数 returns 时被销毁,这通常是一件好事——但如果您需要 someStackObject
保留即使在您的函数返回后仍然存在。
如今,大多数人会完全避免使用 raw/C-style 指针,因为它们非常容易出错。在堆上分配对象的现代 C++ 方法如下所示:
std::shared_ptr<myClass> pointer = std::make_shared<myClass>();
... 这是首选,因为它为您提供了一个堆分配的 myClass 对象,只要至少有一个 std::shared_ptr 指向它(很好),但也将在没有 std::shared_ptr 指向它的那一刻自动删除(更好,因为这意味着没有内存泄漏并且不需要显式调用 delete
,这意味着没有潜在的双删除)