关于C++的基本问题内存管理

发布于 2024-10-19 11:32:53 字数 519 浏览 6 评论 0原文

// 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;
}

通常我不关心内存,但我想清楚地了解, cat1cat2ab 存在吗?在栈中还是在堆中?

@BoPerson:你是对的,我应该使用b = new int(0)。但对我来说更有趣的是,当对象 Cat 在堆中创建时,变量 a 在哪里? a 也在堆中吗?堆中的指针 b 也指向堆中的内存,对吗?

// 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;
}

Usially I don't care about memory, but I want to understand clearly, in what memory do cat1's and cat2's a and b exist? In stack or in heap?

@BoPerson: You're right, I should have used b = new int(0). But it's more interesting for me, where is variable a when object Cat is created in heap? a in heap, too? And pointer b in heap too and it points to memory in heap, right?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

多情出卖 2024-10-26 11:32:53

让我就地注释和回答。

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 ;-)
}

正如您在标题中提到的内存管理:当堆栈变量超出范围时,它们会自动被破坏。即cat1cat2占用的空间(一个Cat,一个指针)在离开main()时会被回收。另外,对于 cat1,将调用析构函数。在您的情况下,没有显式析构函数,但如果 Cat 具有带有析构函数的属性,则会自动生成自动析构函数。

对于指针来说,当指针被破坏时,所指向的对象不会自动被破坏。如果你想要这样,你应该看看像 std::auto_ptr<> 这样的智能指针。 (或 Qt 中的 QScopedPoiner),它为您提供一个类似指针的对象,当 auto_ptr 被破坏时,它确实会破坏所指向的对象(通过调用它的 delete )。

当不使用智能指针时,您需要注意使用删除运算符手动销毁指向的对象。请注意在当前作用域的每个返回路径上执行此操作(例如多次返回、引发异常)。

Let me annotate and answer in-place.

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 ;-)
}

As you refer to memory management in your title: Stack variables get destructed automatically when they fall out of scope. I.e. the space occupied by cat1 and cat2 (one Cat, one pointer) will be recovered when leaving main(). Also, for cat1, the destructor will be called. In your case, there is no explicit destructor but if Cat had attributes with destructors, an automatic destructor would get auto-generated.

For pointers, the object pointed to is not automatically destructed when the pointer gets destructed. If you want that, you should have a look at smart pointers like std::auto_ptr<> (or QScopedPoiner in Qt) which gives you a pointer-like object which will indeed destruct the pointed-to object (by calling delete on it) when the auto_ptr gets destructed.

When not employing smart pointers, you need to take care to manually destruct the pointed-to-objects using the delete operator. Take care to do it on every return-path from your current scope (multiple returns, thrown exceptions, e.g.).

一影成城 2024-10-26 11:32:53

new 关键字将对象分配到堆中。虽然您的第一个示例将内存分配给堆栈。

Cat cat1; //stack

Cat* cat2 = new Cat(); //heap

堆栈内存不像堆内存那样容易获得。基本上,您将内存与 new 一起存储在堆上,并将该地址存储在指针中。

堆上的内存也可以被删除。使用“删除”命令。这使得你的程序运行更有效。

我是否遗漏了任何关键指针?

编辑:不再使用时应删除堆上的内存,不仅仅是为了提高效率,也是为了避免程序膨胀。 (内存泄漏)- 谢谢@Felice Pollano

The new keyword allocates your object to the heap. While your first example allocated memory to the stack.

Cat cat1; //stack

Cat* cat2 = new Cat(); //heap

Stack memory is not as readily available as heap memory. Basically, you store memory on the heap with the new and store that address in a pointer.

Memory on the heap can also be deleted. Using the 'delete' command. Which makes your program run more efficiently.

Am I missing any key pointers anyone?

EDIT: memory on the heap should be deleted when no longer in use, not just for efficency, but to avoid the program inflate. (Memory Leaks) - Thanks @Felice Pollano

怎言笑 2024-10-26 11:32:53

cat1 分配在堆栈上。该类为 8 个字节(如果您的平台上的整数和指针为 4 个字节)。前4个字节是整数a。第二个4字节是整数b。

cat2 分配在堆内存中。否则与上面完全相同。

堆栈变量是“有作用域的”。这意味着当堆栈帧被弹出(即退出函数)时,它被释放并调用其解构函数。

另一方面,堆变量将一直保留,直到您“删除”内存为止。

另请注意,您的构建格式错误。 “*b”取消引用指针(即也获取指针指向的数据)。然后分配 0。出现的问题是 b 没有指向任何确定的内存,因此您将 0 写入可能不在进程地址空间中的未知内存位置。我本以为你的意思是“b = NULL;”

cat1 is allocated on the stack. The class is 8 bytes (if ints and pointers are 4 bytes on your platform). The first 4 bytes is the integer a. The second 4 bytes is the integer b.

cat2 is allocated in heap memory. Otherwise its exactly the same as above.

Stack variables are "scoped". This means that when the stack frame is popped (ie exiting the function) it is free'd and its deconstructor is called.

Heap variables on the other hand will hang around until you "delete" the memory.

Also note that your constructed is malformed. "*b" dereferences the pointer (ie gets at the data the pointer is pointing too). You then assign 0. The problem that arises is that b does not point at any determined memory so you are writing 0 to an unknown memory location which may not be in your processes address space. I would have thought you really mean "b = NULL;"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文