`
anson_xu
  • 浏览: 512994 次
  • 性别: Icon_minigender_1
  • 来自: 惠州
社区版块
存档分类

C++——指针,堆栈,引用,函数

 
阅读更多

C++——指针,堆栈,引用,函数

一. 指针

    声明: int *a = 3;   声明了一个int类型的指针变量a,初始值为3。

    赋值: int b = 3; a = &b; 将变量a的值(即地址)指向b,得到 *a == 3。

指针的好处:

    1. 处理堆中存放的大量数据;

    2. 快速访问类的成员数据和函数;

    3. 以别名方式向函数传递参数。

const与指针:

    指向常量的指针 是指针的值(地址)可以修改,可以指向其它const对象,但指针所指向的对象不能修改。

如:

     const double *a;

     const double b = 5.0;

     a = &b;        //right

     *a = 3.14     //error,不能通过指针来修改所指对象。

 

    常指针 是指针的值不能修改,但指针所指向的对象却可以修改。

如:

      double* const a;

      a = &b;       //error,指针a是一个常指针

      *a = 3;       //right

 

二. 堆和栈

程序在内存中的存放形式有:

1. 栈区。由编译器自动分配并释放,一般存放函数参数,局部变量等。

2. 堆区。由程序员分配并释放,若程序员不释放,程序结束后由操作系统回收。

3. 静态区(全局区)。全局变量和静态变量,程序结束后由系统释放。

4. 文字常量区。常量字符串,程序结束后由系统释放。

5. 程序代码区。函数体的二进制代码。

6. 寄存器区。用来保存栈顶指针和指令指针。

    栈中存放的数据时临时的,全局变量可以解决这个问题,但它永远不会被释放,除非程序结束,并且它的值很容易被修改,使用堆就可以解决这两个问题。

堆与栈的区别

1. 内存申请方式不同

    栈:自动,如int a; 就在内存中开辟了8个字节的空间。

    堆:需要程序员自己申请,因此也需指明变量的大小。

2. 系统响应不同

    栈:只要栈的剩余空间大于申请空间,就提供内存,否则提示overflow,也就是栈溢出。

    堆:系统首先遍历空闲地址链表,找到符合要求的就删除该空闲地址链表,然后在这块区域的首地址处记录大小(效率低,容易产生碎片)。

3. 空间大小不同

    栈:连续内存区域,2M,小量数据。

    堆:不连续,通过链表串联,大量数据。

总结

    栈与堆结合,在存储大型数据,将数据放在堆中,将指向该数据的指针放到栈中。

 

三. 用指针创建堆中的对象

    堆中的每个内存单元都是匿名的,因此必须先在堆中申请一个内存单元地址,然后把它保存到一个指针中,这样只有使用指针才能访问该内存单元的数据

    用new创建一个对象并分配内存

                                  int *p = new int;

                                  delete p;             //释放p所指向的内存空间

                                  p = 0;                  //使用delete后最好将指针清零

    用malloc

                                  int *p = (int *)malloc(sizeof(int));

                                  free(p);

 

关于new/delete与malloc/free

    1. new/delete是运算符,malloc/free是函数。

    2. new除了分配内存,还调用了构造函数,同理delete也会调用析构函数;而malloc/free只会分配内存,不会执行构造函数和析构函数。

    3. 内存泄露对于malloc和new都可以检查出来,区别是new可以指明是哪个文件的哪一行,malloc没有这些信息。

 

内存泄露

   指针消失,计算机再也找不到该内存区域,好像丢失了这块内存一样。

    例:

                                int *p= new int;

                                p = new int;

    先前申请的8个字节空间就丢失,再也找不到了。

 

四. 引用

   引用就是别名常量,它只能被初始化(不能赋值),跟古代的女人一样,一旦嫁给某人就永远属于他。

                                int a = 3;

                                int &ra = a;  //&在这里是引用运算符,ra是a的引用,也就是a的别名,地址与a相同。

   引用在函数传参上很方便有效。

 

五. 函数传参

    一般分为值传递和地址传递(或者别名)两种:

 

Cpp代码  收藏代码
  1. #include <iostream>   
  2. #include <stdio.h>   
  3. using   namespace  std;  
  4.   
  5. /*  
  6. 按值传递需要建立参数的副本,当传递较大的对象时,需要用引用或者指针。  
  7. 在按值传递的过程中,不仅需要复制对象,还要调用默认复制构造函数,该函数的作用就是创建某个对象的临时副本;  
  8. 返回时,副本会被删除,因此也会调用析构函数。  
  9. 参数传递中:int* const a(指针的值不能边,指针所指向的对象的值可以变) 等同于 int& a(别名常量,a不能指向其他对象,但值可以改变)  
  10. const int* const a 等同于 const int& a  
  11. */   
  12. class  A  
  13. {  
  14.     public :  
  15.     A(){printf("构造函数执行\n" );}  
  16.     A(A&) {printf("复制构造函数执行\n" );}  
  17.     ~A() {printf("析构函数执行\n" );}  
  18. };  
  19.   
  20. A fuc(A one)  
  21. {  
  22.     return  one;  
  23. }  
  24.   
  25. void  SwapByValue( int  a,  int  b)  
  26. {  
  27.     int  t;  
  28.     t = a;  
  29.     a = b;  
  30.     b = t;  
  31. }  
  32.   
  33. void  SwapByPoint( int * a,  int * b)  
  34. {  
  35.     int  t;  
  36.     t = *a;  
  37.     *a = *b;  
  38.     *b = t;  
  39. }  
  40.   
  41. void  SwapByRef( int  &a,  int  &b)  
  42. {  
  43.     int  t;  
  44.     t = a;  
  45.     a = b;  
  46.     b = t;  
  47. }  
  48.   
  49. int  main()  
  50. {  
  51.     int  a=3,b=4;  
  52.     SwapByValue(a,b);  
  53.     printf("%d %d\n" ,a,b);  
  54.     SwapByPoint(&a,&b);  
  55.     printf("%d %d\n" ,a,b);  
  56.     SwapByRef(a,b);  
  57.     printf("%d %d\n" ,a,b);  
  58.     A a1;  
  59.     A b1;  
  60.     b1 = fuc(a1);  
  61.     return  0;  

分享到:
评论

相关推荐

    c++学习笔记(c++ 线程 指针 调试 编码)

    理解指针的引用、解引用、空指针、野指针以及指针与数组的关系是学习C++不可或缺的部分。 接下来是调试技巧:在编写C++程序时,调试是解决问题的关键步骤。GDB是一个强大的命令行调试器,可以在源代码级别跟踪程序...

    网络渗透--《C++中溢出覆盖虚函数指针技术》

    《C++中溢出覆盖虚函数指针技术》是一份深入探讨网络安全中漏洞利用的专题文档,主要关注C++编程语言中的一个特定安全问题:缓冲区溢出导致的虚函数指针覆盖。在这个主题中,我们将详细解析这个问题的原理、危害以及...

    C++指针—指针讲解.ppt"

    C++中的指针是编程中一个非常重要的概念,它提供了对内存...理解指针的声明、初始化、访问以及其与数组、函数参数和返回值的关系,是C++程序员必备的技能。在实际编程中,合理运用指针可以显著提升程序的性能和功能。

    C++用堆栈储存迷宫,并寻找路径

    - `IsEmpty()` 函数检查堆栈顶部指针是否为 `NULL`,以此判断堆栈是否为空。 #### 二、迷宫路径寻找算法 1. **迷宫表示**:迷宫通过二维数组 `maze` 表示,其中 `0` 表示可通行,`1` 表示墙壁,而 `-1` 表示已...

    C++对象在堆栈区的析构

    在C++编程中,对象的内存管理是一个关键概念,尤其是涉及到堆栈(stack)和堆(heap)这两种内存区域的对象创建与销毁。本篇将详细探讨C++对象在堆栈区的析构这一主题。 首先,理解堆栈和堆的区别至关重要。堆栈是...

    C#调用C++动态库,执行回调函数并传递结构体参数

    C++的回调函数需要考虑函数指针的调用约定,通常使用`__stdcall`约定,以确保调用者清理堆栈。 在C#中定义回调函数的委托类型: ```csharp [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate void ...

    剖析C++函数调用约定

    C++函数调用约定是编程过程中非常重要的概念,它规定了函数调用时参数传递的顺序、谁负责清理堆栈以及函数名是否需要修饰。在Visual C/C++编译器中,有四种主要的函数调用约定:__cdecl、__stdcall、__fastcall和...

    数据结构实习全部C++ 指针

    本实习项目旨在深入理解和应用C++指针在数据结构中的运用。 在C++中,指针是一个变量,其值为另一个变量的地址。理解指针的工作原理至关重要,因为它们在创建复杂数据结构如链表、树、图等时起着关键作用。例如,在...

    C C++语言函数参数传递及函数调用约定的探讨

    ### C/C++语言函数参数传递及函数调用约定的探讨 #### 摘要 本文主要探讨了C/C++语言中函数之间的参数传递机制以及计算机如何处理函数调用中的参数,即函数调用约定。文章重点分析了值传递与地址传递这两种主要的...

    C-C++中堆栈的区别

    在C++中,可以使用`new`运算符或者`malloc`函数来动态地申请和释放堆内存。堆上的内存分配是不连续的,类似于链表结构,因此可以灵活地分配不同大小的内存块。然而,由于手动管理,程序员必须负责确保正确释放内存,...

    C++异常中的堆栈跟踪

    测试程序通常会模拟各种异常情况,例如除零错误、空指针引用等,以确保异常处理和堆栈跟踪功能的正确性。测试应覆盖不同的代码路径,包括递归调用、多线程环境等,以验证在复杂情况下堆栈跟踪的准确性和稳定性。 ...

    堆栈数据结构的c++实现

    在计算机科学中,堆栈常用于函数调用、表达式求值、内存管理等多种场景。主要操作包括: 1. 入栈(Push):将元素添加到堆栈的顶部。 2. 出栈(Pop):移除堆栈顶部的元素。 3. 查看顶部元素(Top):不移除地查看...

    高质量C++编程指南——教你如何提高C++编程质量

    - **内存错误及其对策**:常见的内存错误包括空指针解引用、数组越界访问等,这些错误可能导致程序崩溃或数据损坏。 - **指针与数组的区别**:虽然指针和数组在很多情况下可以互换使用,但它们在内存布局和操作上有...

    C_C++指针经验总结

    在C和C++编程语言中,指针是一个至关...提供的"**C_C++指针经验总结.pdf**"文档应该会进一步细化这些概念,提供实用的示例和技巧,"**说明.txt**"和"**使用说明.url**"可能包含更多关于如何理解和应用这些知识的指导。

    C~C++程序员实用大全——C~C++最佳编程指南.pdf(1)

    《C~C++程序员实用大全——C~C++最佳编程指南》是一本为C和C++程序员量身定制的综合教程,旨在提供全面且深入的编程指导。这本书涵盖了C和C++的基础到高级主题,是提升技能和深入理解这两种语言精髓的重要资源。 ...

    关于C和C++中函数的调用约定.doc

    在C和C++编程中,函数的调用约定(Calling Convention)和函数名修饰规则(Decorated Name)是两个至关重要的概念,它们直接影响到程序的链接和执行过程。当混合使用C和C++代码,或者在C++程序中调用第三方非C++库时...

    通过EBP EIP来找函数调用堆栈

    在x86架构的处理器上,通常使用两个寄存器——EBP(扩展基址寄存器)和EIP(指令指针寄存器)来辅助管理这个堆栈。 EBP寄存器在函数调用时保存了当前帧的基地址,也就是上一个函数的EBP值,这使得我们能够追溯到...

    30天掌握C++精髓——经典教程

    根据提供的标题、描述以及部分模糊的内容,我们可以推测这是一份关于C++编程的学习教程,旨在帮助读者在30天内掌握C++的核心概念和技术。下面将根据这些信息生成相关的知识点。 ### C++基础 #### 1. C++简介 - **...

    车库 C++ 堆栈 代码

    1. **构造函数 `SqStack()`**:创建一个栈实例,并分配内存空间给栈底元素。如果内存分配失败,则会退出程序。 2. **判断栈是否已满 `SFull()`**:如果栈顶指针指向的位置等于栈底加栈的最大容量,则表示栈已满;...

Global site tag (gtag.js) - Google Analytics