作用域和内存分配

局部

比如函数内定义的对象,分配在上,离开作用域时释放内存

全局

程序内全局可见,生命周期为整个程序运行期间

动态分配的内存

可见性和生命周期介于局部和全局之间,使用new和delete操作符进行内存的分配和释放

动态分配的内存是无名的,new无法为其分配的对象命名,而是返回一个指向该对象的指针

内存泄漏(memory leak)

void fun()
{
    int *p = new int(1);
    // delete p;
}

离开函数作用域之前没有调用delete p,指针p是局部的,唯一的指向刚才分配的内存的指针,因此再也没有办法能够取得刚才分配的内存的地址了,也无法释放了

自定义类是否使用new的区别

不使用new
#include <iostream>
using namespace std;

class B {};

class A
{
    public:
    B fieldB;
};

int main()
{
    A a1 = A();
    B b = B();
    a1.fieldB = b;
    A a2 = A();
    a2.fieldB = b;
    cout << "a1:" << &(a1.fieldB) << endl;
    cout << "a2:" << &(a2.fieldB) << endl;
    
    return 0;
}

输出

a1:0x7fff7c5bd2df
a2:0x7fff7c5bd2dd
  • 对象a的所有需要的内存在调用构造函数之后就已经全部分配完毕(fieldB这部分内存在A对象上),不论是否对fieldB进行赋值,fieldB所占用的内存大小不会改变
  • 虽然a1和a2的fieldB都用b来赋值,但是两者并不是同一个对象(地址不同),每次赋值都产生了一个新的B对象的拷贝
使用new
#include <iostream>
#include <string>
using namespace std;

class B {};

class A
{
    public:
    B *fieldB;
    int *intValue;
};

A Test()
{
    A a1 = A();
    B b = B();
    a1.fieldB = &b;
    A a2 = A();
    a2.fieldB = &b;
    A a3 = A();
    a3.fieldB = new B();
    A a4 = A();
    a4.fieldB = a3.fieldB;
    cout << "a1:" << (a1.fieldB) << endl;
    cout << "a2:" << (a2.fieldB) << endl;
    cout << "a3:" << (a3.fieldB) << endl;
    cout << "a4:" << (a4.fieldB) << endl;
    
    A a5 = A();
    int i = 4;
    a5.intValue = &i;
    // 用于覆盖之前栈内存的i的值
    int another = 5;
    return a5;
}

int main()
{
    A a = Test();
    cout << "a.intValue:" << (*(a.intValue)) << endl;
    
    return 0;
}

输出

a1:0x7fffb05b95ef
a2:0x7fffb05b95ef
a3:0x1c76e70
a4:0x1c76e70
a.intValue:0
  • a1和a2的fieldB指向的是局部变量(分配在栈上),离开main函数作用域则会回收
  • a3和a4的fieldB指向同一个new产生的动态对象,离开main函数作用域仍存在
  • 指针之间的赋值不会产生对象的拷贝,而是指向同一个对象
  • Test中的a指向一个临时对象i,离开Test函数后,i已经被释放,函数外的a指向的地址的值是不确定的(视编译器而定)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值