【C++】指针2 与内存

指针如何创建动态内存?
指针如何释放所创建的动态内存?
野指针的处理办法?

在C++程序中,一些变量在整个程序中都是可见的,称为全局变量。一些只能在一个函数中可知,称为局部变量。

一个程序将操作系统分配给其运行的内存块分为4个区域:
1)代码区,存放系统的代码,即程序中的各个函数代码块。
2)全局数据区,存放程序的全局数据和静态数据。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。
3)堆区,存放程序的动态数据。程序在运行的时候用new申请任意多的内存,程序员自己负责在何时用delete释放内存。
4)栈区,存放程序的局部数据,即各个函数中的数据。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。

在C++中,申请和释放堆中分配的存贮空间,分别使用new和delete的两个运算符来完成:
例如:1、 int *pi=new int(0);
它与下列代码序列大体等价:
2、int ival=0, *pi = & ival;

区别:

pi所指向的变量是由库操作符new()分配的,位于程序的堆区中,并且该对象未命名。

new运算符返回的是一个指向所分配类型变量(对象)的指针。对所创建的变量或对象,都是通过该指针来间接操作的,而动态创建的对象本身没有名字。

在堆中建立动态一维数组

指针变量名=new 类型名[下标表达式];

注意:“下标表达式”不是常量表达式,即它的值不必在编译时确定,可以在运行时确定。

例如以下代码:

int n;
    char *pc;
    cout << "请输入动态数组的元素个数" << endl;
    cin >> n;
    pc = new char[n];
    strcpy(pc, "veryGood");
    cout << pc << endl;
    delete[] pc;
    system("pause");

在堆中释放指针所创立的内存

⑴.用初始化式(initializer)来显式初始化
int *pi=new int(0);
⑵.当pi生命周期结束时,必须释放pi所指向的目标:
delete pi;

注意这时释放了pi所指的目标的内存空间,也就是撤销了该目标,称动态内存释放(dynamic memory deallocation),但指针pi本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放,需要注意的是任何类型指针的都会占用四个字节的内存。

特别需要注意的是,如果该指针又指向了别处,那么在释放以前务必要保证指针从新指回原来的内存地址:

运行时程序会奔溃:

int *pi=new int(9);
    int ival=5;
    pi=&ival;
    delete pi;
    system(“pause”);

在堆中动态释放指针所创建的数组内存

delete [ ]指向该数组的指针变量名

注意:方括号非常重要的,如果delete语句中少了方括号,因编译器认为该指针是指向数组第一个元素的,会产生回收不彻底的问题(只回收了第一个元素所占空间),加了方括号后就转化为指向数组的指针,回收整个数组。delete [ ]的方括号中不需要填数组元素数,系统自知。即使写了,编译器也忽略。

如果指向数组的指针移动了,或者指向了别的内存地址,那么在释放前务必要将该指针回归原位,最快捷的办法是做原始内存地址的备份。

int *pi=new int[10];
    int *temp = pi;
    int ival = 20;
    pi = &ival;
    pi = temp;
    delete []pi;
    system(“pause”);
常见的内存错误及对策

1)内存分配未成功,却使用了它。
int *pB;
*pB=10;
解决办法:在使用内存之前检查指针是否为NULL。
assert(p!=NULL) 、if(p==NULL) 或if(p!=NULL)

2)忘记了释放内存,造成内存泄露。
含有这种错误的函数每被调用一次就丢失一块内存。

3)释放了内存却继续使用它

4)使用delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。
“野指针”不是NULL指针,是指向“垃圾”内存的指针。

如果要保存指针的内存地址,则需要使用到二级指针。

void类型的指针可以保存任何类型数据的内存地址,只不过在访问数据或者修改数据的时候,需要将指针类型转换为所保存的数据类型。

int ival = 10;
void *pv = &ival;
cout<<*(int*)pv<<endl;

在32位机器中整型与指针都占4个字节,内存的表现方式也都是二进制整数,但是整型和指针所表示的数据类型不同。无法从整型转换为整型的指针

但是整型类型被强制转换为整型指针类型后,也可以给指针赋值,这个时候要注意的是指针保存的并不是整型数据所在的内存地址。

int ival = 0x18ff00;
    int *pi = (int*)ival;
    cout<<pi<<endl;
    cout<<*pi<<endl;
    cout<<&ival<<endl;
    system(“pause”);

二维数组的创建与释放

int** pii = new int*[5];
    for (int i = 0; i < 5; i++)
    {
        *(pii+i) = new int[5];
    }

    for (int j = 0; j < 5; j++)
    {
        for (int u = 0; u < 5; u++)
        {
            *(*(pii + u) + j) = u;
            cout << *(*(pii + u) + j);
        }
        cout << endl;
    }

    cout << sizeof(pii) << endl;

    for (int v = 0; v < 5; v++)
    {
        delete[] pii[v];
        pii[v] = NULL;
    }
    delete[] pii;
    pii = NULL;

注意:sizeof(数组名)->数组所占内存空间;sizeof(指向数组的指针)->4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值