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;}
- 栈大小1MB(默认值),申请栈空间1MB
后果:程序解体,stack overflow
- 栈大小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;}
- 栈大小1MB,申请堆1MB
后果:程序失常 - 栈大小1MB,申请堆10MB
后果:程序失常