`
隐形的翅膀
  • 浏览: 502122 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

指针的释放

 
阅读更多
使用 new 得来的空间,必须用 delete 来释放;使用 new [] 得来的空间,必须用 delete [] 来释放。彼此之间不能混用。用 new [] 分配出连续空间后,指针变量“指向”该空间的首地址。

和指针变量相比, 数组没有一个单独的内存空间而存放其内存地址。即:指针变量p是一个独立的变量,只不过它的值指向另一段连续的内存空间;而数组arr,本身代表的就是一段连续空间。数组是“实”的地址,不能改变。当你和定义一个数组,则这个数组就得根据它在内存中的位置,得到一个地址,如上图中的“0x1A000000”。只要这个数组存在,那么它终生的地址就是这个值。指针是一个“虚”的地址,可以改变地址的值。

数组与指针的相似之处

通过+来得到指定元素,也可通过[]指定元素

int arr[20]; //定义
arr[0] = 100; //让第一个元素为100
for (int i = 1; i < 20; i++)
{
    arr[i] = arr[i-1] + 50;
}
for (int i = 0; i < 20; i++) //输出
{
    cout << arr[i] << endl;
}
//通过+来得到指定元素,也可通过[]
cout << *(arr + 0) << endl; //*(arr+0) 等于 *arr
cout << *(arr + 1) << endl;
cout << *(arr + 1) << endl;


指针

int *p = new int[20]; //定义
p[0] = 100; //让第一个元素为100
for (int i = 1; i < 20; i++)
{
    p[i] = p[i-1] + 50;
}
for (int i = 0; i < 20; i++) //输出
{
    cout << p[i] << endl;
}
//通过+来得到指定元素,也可通过[]
cout << *(p + 0) << endl; //*(p+0) 等于 *p
cout << *(p + 1) << endl;
cout << *(p + 1) << endl;


两者不同之处

数组
1. 不能通过对数组本身+或-来改变数组的位置
2. 数组所带的空间由系统自动分配及回收,无须也无法由程序来直接释放
3. 可以定义并初始化

//定义并初始化
int arr[10] = {0,1,2,3,4,5,6,7,8,9}; 

//不能通过对数组本身+或-来改变数组的位置
arr = arr + 1; //错!
cout << *arr << endl;
arr++; //错!
cout << *arr << endl;
arr--; //错!
cout << *arr << endl;

//数组所带的空间由系统自动分配及回收,无须也无法由程序来直接释放


指针
1. 定义并且生成空间,但不能直接初始空间的内容
2. 可以通过+或-操作直接改变指针
3. 指向连续空间的指针,必须使用delete[]来释放
//定义并且生成空间,但不能直接初始空间的内容
int *p = new int[20] {0,1,2,3,4 ……}; // 错!

//只得通过循环一个个设置
for (int i=0; i<20; i++)
{
    p[i] = i;
}

//可以通过+或-操作直接改变指针
p = p + 1;
cout << *p << endl;

p++;
cout << *p << endl; 

p--;
cout << *p << endl;

//指向连续空间的指针,必须使用delete[]来释放
delete [] p;



delete/delete[]的几个注意点

a. 指针通过 new 或 new[] ,向系统“申请”得到一段内存空间,这段内存空间必须在不需要将它释放了。
b. 一个指针被删除时,应指向最初的地址
c. 已释放的空间,不可重复释放
    aa. 直接删除同名指针
    bb  重复删除同一指向的多个指针
    cc  删除指向某一普通变量的指针



1. 1. 指针通过 new 或 new[] ,向系统“申请”得到一段内存空间,这段内存空间必须在不需要将它释放了。
int* p = new int[100]; 
 
int girl[100];  
  
p = girl;  
  
delete [] p;

灾难在 delete [] p 时发生。我们原意是要释放p最初通过new int[100]而得到的内存空间,但事实上,p那时已经指向girl[100]了。
结果,第一、最初的空间并没有被释放。第二、girl[100] 本由系统自行释放,现在我们却要强行释放它。

2. 一个指针被删除时,应指向最初的地址
当一个指针通过 +,- 等操作而改变了指向;那么在释放之前,应确保其回到原来的指向。如下所示:在 delete [] p 时,p指向的是第二个元素,结果该释放将产生错位:第一个元素没有被释放,而在最后多删除了一个元素。
int *p = new int[3];

*p = 1;
cout << *p << endl;

p++; //p的指向改变了,指向了下一元素

*p = 2;
cout << *p << endl;

delete [] p; //错误的释放

如何消除这一严重错误呢?
第一种方法是把指针正确地"倒"回原始位置:
p--;

delete [] p;


但当我们的指针指向变化很多次时,在释放前要保证一步不错地一一退回,会比较困难。所以另一方法是在最初时“备份”一份。在释放时,直接释放该指针即可。
int* p = new int[3];

int* pbak = *p; //备份

//移动 p

……

delete [] pbak; //释放

由于pbak正是指向p最初分配后的地址,我们删除pbak,就是删除p最初的指向。此时我们不能再删除一次p。这也就引出new / delete 及 new[] / delete[] 在本章的最后一个问题。

3. 已释放的空间,不可重复释放
第一种最直接:
int* p = new int(71);

cout << *p << endl; 

delete p; //OK!

delete p; //ERROR! 重复删除p


第二种为重复删除同一指向的多个指针
int* p1 = new int(71);

int* p2 = p1; //p2和p1 现在指向同一内存地址

cout << *p1 << endl;

cout << *p2 << endl;

delete p1; //OK

delete p2; //ERROR! p2所指的内存,已通过delete p1而被释放,不可再delete一次


同样的问题,如果你先删除了p2,则同样不可再删除p1

delete p2; //OK

delete p1; //ERROR


第三种为删除指向某一普通变量的指针

int a = 100;

int* p = &a;

delete p; //ERROR 


p 不是通过new 得到新的内存空间,而是直接指向固定变量a。所以删除p等同要强行剥夺a的固有空间,会导致出错。


分享到:
评论

相关推荐

    C++指针 数组 内存释放.docx

    C++指针数组内存释放 C++指针是一种基本变量,包含一个实际的数据,该数据代表一个可以找到实际信息的内存地址。指针是C++编程中非常重要的概念,许多程序和思想依靠指针作为他们设计的基础。 定义指针变量 定义...

    c++11 智能指针(csdn)————程序.pdf

    * 获取原始指针:使用 get() 函数获取原始指针,但需要小心使用,因为如果智能指针释放了对象,返回的指针所指向的对象也就消失了。 * 指定删除器:可以在智能指针初始化时指定删除器,例如使用 lambda 表达式 std::...

    C指针详解(经典,非常详细).pdf

    - 注意指针释放:动态分配的内存要使用完毕后及时释放,防止内存泄漏。 综上所述,指针是C语言中的高级特性,使用它需要对语言的内存管理和类型系统有深入的理解。通过逐步学习和实践,可以掌握指针的各种用法,写...

    C语言指针学习总结 简单全面

    C语言指针学习总结 简单全面 本文总结了C语言指针的...* 双重释放:指针释放了多次的指针。 这些问题如果不被注意,可能会导致程序崩溃或数据泄露。 指针是 C 语言中一个非常重要的概念,需要我们认真对待和学习。

    smartptr——基于自动引用计数的智能指针

    它可以接管任意类型的指针,所以你只需要放心大胆的new出任意对象,然后用智能指针去接管它,而不用担心在什么地方去delete,这个对象会最后一个接管它的智能指针释放它或者被销毁时而被delete;如果贪图方便,你...

    wince内存释放,wince内存释放

    - 避免空指针释放:确保释放的内存指针有效,防止多次释放同一内存块。 - 使用智能指针:在C++环境中,可以使用智能指针(如`auto_ptr`,`unique_ptr`,`shared_ptr`等)自动管理内存,防止泄漏。 5. 内存泄漏...

    悬挂指针1

    - **指针释放后立即置零**:释放对象后,将指针设为`NULL`,这样后续检查时可以发现该指针不再有效。 - **智能指针**:在C++中,智能指针(如`std::unique_ptr`和`std::shared_ptr`)可以自动管理对象的生命周期,...

    C语言中指针的使用方法及常见问题.pdf

    4. 指针释放后继续使用:释放指针所指向的内存后,不应再使用该指针,否则可能导致程序崩溃。 掌握指针的使用是学习C语言的关键。理解其基本概念、声明、赋值以及指针运算,有助于编写更高效、灵活的代码,同时也能...

    指针 指针教程 指针练习

    指针是C/C++编程语言中的核心概念,它在程序设计中扮演着至关重要的角色。指针是一个变量,其存储的是内存地址,该地址指向另一个变量。理解并熟练使用指针,是提升编程技能的关键步骤。 一、指针的基础概念 1. ...

    dangling-pointer-rampage-master.rar

    1. **指针释放后未重置**:当一个动态分配的内存块被`free()`或`delete`释放后,如果不立即将相应的指针设为`NULL`,该指针就成为悬空指针。之后若尝试通过该指针访问内存,将导致未定义行为。 2. **指针超越数组...

    C指针 C指针C指针C指针C指针C指针

    C指针是C语言中的核心概念,它是编程中不可或缺的一部分,尤其对于理解内存管理和程序设计的底层机制至关重要。本文将深入探讨C指针的基本概念、使用方法及其在程序设计中的重要性。 首先,理解C指针的基本定义是...

    CONST指针指针

    当我们谈论`const`指针时,我们实际上是在讨论如何使用`const`修饰指针变量、指针所指向的变量以及同时修饰两者的情况。理解这些概念对于深入学习C语言至关重要。 1. **const修饰指针本身** 当`const`修饰指针本身...

    C的指针数组和数组指针

    - **指针删除与堆空间释放**:释放指针指向的内存后,指针成为悬空指针,不应再次使用。 - **内存泄漏**:忘记释放分配的内存会导致内存泄漏。 - **重复释放**:重复释放同一段内存可能会导致程序崩溃或不稳定行为。...

    指针的用法大全,指针与数组,指针详解

    C++中的`new`和`delete`操作符分别用于动态分配和释放内存,而它们的工作离不开指针。`int *p = new int;`会分配一个整型空间,并返回其地址给p。当不再需要该内存时,应使用`delete p;`来释放。 指针与指针数组也...

    NULL指针、零指针、野指针定义及区别

    - 指针指向的对象已被释放或销毁。 - 指针未经初始化。 - 指针被赋予了一个无效的地址。 使用野指针会导致未定义行为,可能会引起程序崩溃或数据损坏。 #### 三、总结 综上所述,NULL指针、零指针、空指针都是...

    Pascal指针 Pascal 指针

    在Pascal编程语言中,指针是一种特殊的数据类型,它允许程序员通过地址直接访问和操作内存中的变量。本文将深入探讨Pascal中...然而,使用时也需要注意正确分配和释放内存,以及确保指针的有效性,避免出现运行时错误。

    智能指针--真正的安全的指针

    在C++中,裸指针的使用容易导致各种内存管理错误,例如忘记释放内存导致的内存泄漏、重复释放内存等问题。而智能指针则通过其内部机制确保了这些情况不会发生。具体来说: 1. **安全性**:智能指针能够确保在对象...

    指针学习 单纯的指针学习

    - 释放内存后,将指针设为`NULL`以防止悬挂指针问题。 ##### 2.4 使用`delete`释放字符串所指向的内存空间 **定义**: 使用`delete`操作符释放之前通过`new`分配的内存空间。 **示例**: ```cpp char *str = new ...

    c++句柄,智能指针 指针间的区别

    智能指针类将指针变量作为成员变量封装起来,在智能指针类对象离开作用域时,会再析构的过程中完成指针的释放。例如,使用auto_ptr智能指针类,可以自动释放所指向的对象内存,避免了手动delete的麻烦。 句柄、智能...

    C指针与陷阱 中文高清版

    悬空指针是指曾经指向已释放内存的指针,而野指针则是指没有明确指向任何有效内存地址的指针,它们都可能导致不可预测的行为。 为了正确使用指针,我们需要掌握以下几点: 1. 初始化:始终确保在使用指针之前对其...

Global site tag (gtag.js) - Google Analytics