一. 指针
声明: 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相同。
引用在函数传参上很方便有效。
五. 函数传参
一般分为值传递和地址传递(或者别名)两种:
-
#include <iostream>
-
#include <stdio.h>
-
using
namespace
std;
-
-
-
-
-
-
-
-
-
class
A
-
{
-
public
:
-
A(){printf("构造函数执行\n"
);}
-
A(A&) {printf("复制构造函数执行\n"
);}
-
~A() {printf("析构函数执行\n"
);}
-
};
-
-
A fuc(A one)
-
{
-
return
one;
-
}
-
-
void
SwapByValue(
int
a,
int
b)
-
{
-
int
t;
-
t = a;
-
a = b;
-
b = t;
-
}
-
-
void
SwapByPoint(
int
* a,
int
* b)
-
{
-
int
t;
-
t = *a;
-
*a = *b;
-
*b = t;
-
}
-
-
void
SwapByRef(
int
&a,
int
&b)
-
{
-
int
t;
-
t = a;
-
a = b;
-
b = t;
-
}
-
-
int
main()
-
{
-
int
a=3,b=4;
-
SwapByValue(a,b);
-
printf("%d %d\n"
,a,b);
-
SwapByPoint(&a,&b);
-
printf("%d %d\n"
,a,b);
-
SwapByRef(a,b);
-
printf("%d %d\n"
,a,b);
-
A a1;
-
A b1;
-
b1 = fuc(a1);
-
return
0;
-
}
分享到:
相关推荐
理解指针的引用、解引用、空指针、野指针以及指针与数组的关系是学习C++不可或缺的部分。 接下来是调试技巧:在编写C++程序时,调试是解决问题的关键步骤。GDB是一个强大的命令行调试器,可以在源代码级别跟踪程序...
《C++中溢出覆盖虚函数指针技术》是一份深入探讨网络安全中漏洞利用的专题文档,主要关注C++编程语言中的一个特定安全问题:缓冲区溢出导致的虚函数指针覆盖。在这个主题中,我们将详细解析这个问题的原理、危害以及...
C++中的指针是编程中一个非常重要的概念,它提供了对内存...理解指针的声明、初始化、访问以及其与数组、函数参数和返回值的关系,是C++程序员必备的技能。在实际编程中,合理运用指针可以显著提升程序的性能和功能。
- `IsEmpty()` 函数检查堆栈顶部指针是否为 `NULL`,以此判断堆栈是否为空。 #### 二、迷宫路径寻找算法 1. **迷宫表示**:迷宫通过二维数组 `maze` 表示,其中 `0` 表示可通行,`1` 表示墙壁,而 `-1` 表示已...
在C++编程中,对象的内存管理是一个关键概念,尤其是涉及到堆栈(stack)和堆(heap)这两种内存区域的对象创建与销毁。本篇将详细探讨C++对象在堆栈区的析构这一主题。 首先,理解堆栈和堆的区别至关重要。堆栈是...
C++的回调函数需要考虑函数指针的调用约定,通常使用`__stdcall`约定,以确保调用者清理堆栈。 在C#中定义回调函数的委托类型: ```csharp [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate void ...
C++函数调用约定是编程过程中非常重要的概念,它规定了函数调用时参数传递的顺序、谁负责清理堆栈以及函数名是否需要修饰。在Visual C/C++编译器中,有四种主要的函数调用约定:__cdecl、__stdcall、__fastcall和...
本实习项目旨在深入理解和应用C++指针在数据结构中的运用。 在C++中,指针是一个变量,其值为另一个变量的地址。理解指针的工作原理至关重要,因为它们在创建复杂数据结构如链表、树、图等时起着关键作用。例如,在...
### C/C++语言函数参数传递及函数调用约定的探讨 #### 摘要 本文主要探讨了C/C++语言中函数之间的参数传递机制以及计算机如何处理函数调用中的参数,即函数调用约定。文章重点分析了值传递与地址传递这两种主要的...
在C++中,可以使用`new`运算符或者`malloc`函数来动态地申请和释放堆内存。堆上的内存分配是不连续的,类似于链表结构,因此可以灵活地分配不同大小的内存块。然而,由于手动管理,程序员必须负责确保正确释放内存,...
测试程序通常会模拟各种异常情况,例如除零错误、空指针引用等,以确保异常处理和堆栈跟踪功能的正确性。测试应覆盖不同的代码路径,包括递归调用、多线程环境等,以验证在复杂情况下堆栈跟踪的准确性和稳定性。 ...
在计算机科学中,堆栈常用于函数调用、表达式求值、内存管理等多种场景。主要操作包括: 1. 入栈(Push):将元素添加到堆栈的顶部。 2. 出栈(Pop):移除堆栈顶部的元素。 3. 查看顶部元素(Top):不移除地查看...
- **内存错误及其对策**:常见的内存错误包括空指针解引用、数组越界访问等,这些错误可能导致程序崩溃或数据损坏。 - **指针与数组的区别**:虽然指针和数组在很多情况下可以互换使用,但它们在内存布局和操作上有...
在C和C++编程语言中,指针是一个至关...提供的"**C_C++指针经验总结.pdf**"文档应该会进一步细化这些概念,提供实用的示例和技巧,"**说明.txt**"和"**使用说明.url**"可能包含更多关于如何理解和应用这些知识的指导。
《C~C++程序员实用大全——C~C++最佳编程指南》是一本为C和C++程序员量身定制的综合教程,旨在提供全面且深入的编程指导。这本书涵盖了C和C++的基础到高级主题,是提升技能和深入理解这两种语言精髓的重要资源。 ...
在C和C++编程中,函数的调用约定(Calling Convention)和函数名修饰规则(Decorated Name)是两个至关重要的概念,它们直接影响到程序的链接和执行过程。当混合使用C和C++代码,或者在C++程序中调用第三方非C++库时...
在x86架构的处理器上,通常使用两个寄存器——EBP(扩展基址寄存器)和EIP(指令指针寄存器)来辅助管理这个堆栈。 EBP寄存器在函数调用时保存了当前帧的基地址,也就是上一个函数的EBP值,这使得我们能够追溯到...
根据提供的标题、描述以及部分模糊的内容,我们可以推测这是一份关于C++编程的学习教程,旨在帮助读者在30天内掌握C++的核心概念和技术。下面将根据这些信息生成相关的知识点。 ### C++基础 #### 1. C++简介 - **...
1. **构造函数 `SqStack()`**:创建一个栈实例,并分配内存空间给栈底元素。如果内存分配失败,则会退出程序。 2. **判断栈是否已满 `SFull()`**:如果栈顶指针指向的位置等于栈底加栈的最大容量,则表示栈已满;...