// main.cpp
class Cat()
{
public:
Cat()
{
a = 0;
(*b) = 0;
}
int a;
int* b;
};
int main(int argc, char* argv[])
{
Cat cat1;
Cat* cat2 = new Cat();
return 0;
}
通常我不关心记忆,但我想清楚地理解,cat1
和cat2
的{{1}}和a
存在于什么记忆中?在堆栈中还是在堆中?
@BoPerson:你是对的,我应该使用b
。但对我来说这更有意思,当在堆中创建对象b = new int(0)
时,变量a
在哪里?堆中也Cat
?并且指针a
也在堆中,它指向堆中的内存,对吧?
答案 0 :(得分:7)
让我注释并就地回答。
class Cat() { public: Cat() { a = 0; // ok: sets the variable a, wherever it lives (*b) = 0; // not ok: stores an integer 0 to wherever b points // since b was never initialized to anything, it can write // anywhere you can imagine. If you are lucky, your compiler // implicitly initializes the pointer to zero such that you // at least get a deterministic segmentation violation. } int a; // an integer variable living wherever Cat gets constructed int* b; // a pointer variable living wherever Cat gets constructed pointing // to wherever it gets set to (b = something) could be heap, stack, // mapped memory, out-of-control (like here) }; int main(int argc, char* argv[]) { Cat cat1; // allocates cat1 on the stack, all attributes (a and b) live // there. Where cat1.b points to is unrestricted. Cat* cat2 = new Cat(); // allocates an object of class Cat on heap, // allocates a pointer variable cat2 on the stack and stores the // pointer to said heap-allocated Cat in it // again, where cat2.b points to is unrestricted. return 0; // maybe never reached due to segfault ;-) }
当您在标题中引用内存管理时:堆栈变量在超出范围时会自动被破坏。即离开main()时,cat1
和cat2
占用的空间(一个Cat,一个指针)将被恢复。此外,对于cat1,将调用析构函数。在您的情况下,没有明确的析构函数,但如果Cat具有析构函数的属性,则会自动生成自动析构函数。
对于指针,当指针被破坏时,指向的对象不会自动被破坏。如果你想要,你应该看看像std :: auto_ptr<>这样的智能指针。 (或Qt中的QScopedPoiner)它给你一个类似指针的对象,当auto_ptr被破坏时,它确实会破坏指向对象(通过调用delete)。
如果不使用智能指针,则需要注意使用delete运算符手动破坏指向对象。注意在当前范围的每个返回路径上执行此操作(多次返回,抛出异常,例如)。
答案 1 :(得分:4)
new关键字将您的对象分配给堆。虽然您的第一个示例将内存分配给堆栈。
Cat cat1; //stack
Cat* cat2 = new Cat(); //heap
堆栈内存不像堆内存那样容易获得。基本上,您使用new将内存存储在堆上,并将该地址存储在指针中。
堆上的内存也可以删除。使用'delete'命令。这使您的程序运行更高效。
我是否遗漏了任何关键指针?
编辑:当不再使用时,应该删除堆上的内存,不仅仅是为了提高效率,还要避免程序膨胀。 (记忆泄漏) - 谢谢@Felice Pollano
答案 2 :(得分:1)
cat1在堆栈上分配。该类为8个字节(如果整数和指针在您的平台上为4个字节)。前4个字节是整数a。第二个4字节是整数b。
cat2在堆内存中分配。否则与上面完全相同。
堆栈变量是“作用域”。这意味着当弹出堆栈框架(即退出函数)时,它将被释放并调用其解构函数。
另一方面,堆变量将一直存在,直到您“删除”内存。
另请注意,您构建的格式不正确。 “* b”取消引用指针(即获取指针指向的数据)。然后分配0.出现的问题是b不指向任何确定的内存,因此您将0写入未知的内存位置,这可能不在您的进程地址空间中。我原本以为你的意思是“b = NULL;”