局部变量内存分配时间、静态变量的初始化时间、常量折叠

内存分配时间

例1 局部变量

void Test1()
{
    …………
    int buf[1024 * 1024];
    …………
}

在windows下,由于栈限制为1M,上面代码可能会栈溢出,因此通过单步调试我们可以知道,局部变量是在进入函数时分配栈内存。

编译器在编译的过程中,遇到函数调用时,会加入几条汇编指令。这些汇编指令的作用是:
1 分配一段栈空间,用于存放被调函数的参数和局部变量。
2 call被用函数。
3 当被调函数返回时释放掉这段分配栈空间。

例2 全局/静态变量

class B
{
public:
    B(){cout << "class B construct" << endl;}
    ~B(){}
};

class A
{
public:
    A(){cout << "class A construct" << endl;}
    ~A(){}

    static B b;
}

B A::b;

void test()
{
    static A a;
}

int main()
{
    test();
    test();
    return 0;
}

上面代码运行,main函数前,会调用B的构造函数,
test函数中第一次static A a时会调用一次A的构造函数

引用自https://segmentfault.com/q/1010000004157283

  • 对于C语言的全局和静态变量,不管是否被初始化,其内存空间都是全局的;如果初始化,那么初始化发生在任何代码执行之前,属于编译期初始化。由于内置变量无须资源释放操作,仅需要回收内存空间,因此程序结束后全局内存空间被一起回收,不存在变量依赖问题,没有任何代码会再被执行!

  • C++引入了对象,这给全局变量的管理带领新的麻烦。C++的对象必须有构造函数生成,并最终执行析构操作。由于构造和析构并非分配内存那么简单,可以说相当复杂,因此何时执行全局或静态对象(C++)的构造和析构呢?这需要执行相关代码,无法在编译期完成,因此C++标准规定:全局或静态对象当且仅当对象首次用到时才进行构造,并通过atexit()来管理对象的生命期,在程序结束之后(如调用exit,main),按FILO顺序调用相应的析构操作!

  • 总结:
    全局变量、文件域的静态变量和类的静态成员变量在main执行之前的静态初始化过程中分配内存并初始化;局部静态变量(一般为函数内的静态变量)在第一次使用时分配内存并初始化。这里的变量包含内置数据类型和自定义类型的对象。

关于全局/静态变量的内存分配问题,上面总结里已经说的很详细了。
但是我有两点不同看法:

  1. 局部静态变量的内存分配应该和全局变量一样,在main函数之前分配好,在第一次调用的时候只是初始化。
  2. 如果注释掉 B A::b(即不对b进行显式初始化),结果就不会调用B的构造函数。因此对于类的静态成员来说,static B b只是声明,B A::b才是定义,而类中如果是B b则是声明且定义。

例3 常量

引用自https://blog.csdn.net/xiazhiyiyun/article/details/71969618

小结
  1. 对于const全局常量,如果初始值是字面值常量,一般会存放在常量表中,编译器在编译过程中就会直接使用常量表中的值来进行语句的操作。如果经过优化,可能会使得直接使用常而放弃存储在常量表中。
  2. 对于编译器没有办法处理的初始值常量,一般就需要分配到内存空间,然后等待运行时进行赋值,取值时候也是从内存空间中提取。
  3. 对于非static 的 const局部变量(如函数中),由于其是局部变量,符号表中将不存在其值,如果需要内存空间也是在栈中进行分配。根据编译器的优化,以及const 变量初始值的不同来决定是否需要分配内存空间。
  4. 对于static 的 const局部变量(如函数中),会根据编译器的优化能力,以及初始值,来决定其是不进行存储,还是直接存储在常量符号表,或者是栈中等等均有可能。
  5. 对于第三点和第四点可以字迹尝试验证。
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值