乐趣区

关于c++:c-对象在栈上还是在堆上

c++ 的对象到底在栈上还是调配在堆上?

首先, 毋庸置疑,应用 new 和 malloc 系列函数调配的对象,肯定是在堆上的。

Object *obj = new Object();

有争议的是

Object obj;

它是在栈上还是在堆上呢?

要答复这个问题,首先咱们须要了解这句话的意思,这句话并不代表在栈上分配内存,它代表的是让 obj 具备“主动存储 (automatic storage)”的性质。所谓的“主动存储”,意思是这个对象的存储地位取决于其申明所在的上下文。如果这个语句呈现在函数外部,那么它就在栈上创建对象,此时 obj 变量和 obj 指代的对象(此时 obj 实质上其实是 obj 指代对象的首地址)都在栈上。
如果这个语句不是在函数外部,而是作为一个类的成员变量,则取决于这个类的对象是如何调配的。思考上面的代码:

class Test{Object obj;}

Test *test = new Test;

test 指针是在栈上,它所指代的对象 Test 是存在堆上,那么 obj 变量和 obj 对象就在堆上。

class Test{Object obj;}

Test test;

test 变量在栈上,test 对象在栈上,那么 obj 变量和 obj 对象就在栈上。

遵循这么一个准则:
指针变量和一般变量由上下文定义,指针所指向的内存在堆上,一般变量所指代的对象由上下文定义。

栈大小

栈大小是有默认值的,如果申请的长期变量太大就会超过栈大小,造成栈溢出。

它的默认值是能够批改的,个别,在 unix-like 平台,栈的大小是由环境变量管制的,所以不能通过设置编译器 (像 gcc) 的任何编译标记来设置;在 windows 平台,栈的大小是蕴含在可执行文件里的,它能够在 visual c++ 的编译过程中设置,但在 gcc 里是不可行的。

办法为:
我的项目 -> 属性 -> 链接器 -> 零碎 -> 堆栈保留大小(字节数)

在个别状况下, 不同平台默认栈大小如下所示(仅供参考)

SunOS/Solaris 8172K bytes (Shared Version)
Linux 10240K bytes
Windows 1024K bytes (Release Version)
AIX 65536K bytes

演示

栈空间

代码

#include <iostream>

class Test {
public:
    Test() { std::cout << "Test" << std::endl;}
    ~Test() { std::cout << "~Test" << std::endl;}

private:
    char a[1024 * 1024];
};

class TestContainer {
public:
    TestContainer() { std::cout << "TestContainer" << std::endl;}
    ~TestContainer() { std::cout << "~TestContainer" << std::endl;}

private:
    Test test;
};

int main(int argc, char* argv[]) {
    TestContainer t;
    while (1) {}
    return 0;
}
  1. 栈大小 1MB(默认值), 申请栈空间 1MB
    后果: 程序解体,stack overflow
  1. 栈大小 1048577(1024*1024+1, 即 1MB 多 1B),申请栈空间 1MB
    后果: 程序失常

堆空间

#include <iostream>

class Test {
public:
    Test() { std::cout << "Test" << std::endl;}
    ~Test() { std::cout << "~Test" << std::endl;}

private:
    char a[1024 * 1024];
};

class TestContainer {
public:
    TestContainer() { std::cout << "TestContainer" << std::endl;}
    ~TestContainer() { std::cout << "~TestContainer" << std::endl;}

private:
    Test test;
};

int main(int argc, char* argv[]) {
    TestContainer* t = new TestContainer;
    while (1) {}
    return 0;
}
  1. 栈大小 1MB, 申请堆 1MB
    后果: 程序失常
  2. 栈大小 1MB,申请堆 10MB
    后果: 程序失常
退出移动版