目录:指针的内容和与之相关的类型
引用
动态内存
内存泄漏和悬挂指针
正文:
指针:指针的定义:存放地址的变量叫做指针变量,简称为指针(指针实现的是间接访问,而对变量名的访问可以叫做直接访问)。
指针的使用:定义:类型名(必须与指向的地址相一致) +*+变量名
初始化:可以有两种初始化的方式:第一种在定义的时侯就直接初始化,比如:int ab=23;int *a=&ab(在这里注意一下,必须直接打变量名,而不能打数值,因为字面型常量并不能直接的体现数值);第二种:先定义,后初始化:int *a; int b = 123; a = &b; cout << *a;差不多就是这么一个过程。(对了在这个过程中你需要体会以下几个东西,指针的内容是一个地址,所以你在初始化的时候,用的是指针本身的内容等于取地址这个变量名,而在初始化的时候,你直接可以去令*P等于这个内容,对了,多提一下,在第二回赋值的时候,你不能用指针指向这个变量名来赋值,这是一个错误的语法,而且,NULL必须大写。)
int a[12][2] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
cout << *(*(a+5)+5);
输出的结果是16
应用:指针的使用也可以改变值的大小,访问指针和访问变量具有同样的效果。
对于运算的改变,指针可以改变位置,即改变指针指向当前位置P的前方和后方第N个数据的地址(
给指针的赋值必须是同类型的,不存在自动转化,可以是同类型变量的地址,同类型的指针。
指针的大小相等代表指向相同的地址,大小相减代表中间差几个这个数据。
引用:引用的定义:应用是C++中新引入的概念,是C中不存在的数据类型。
引用的声明:先定义,后声明。(A:int a;int &b=a;B:引用必须在声明的同时完成初始化,而不能在声明后,完成初始化。C引用不可以更改:)
引用的使用: 直接使用就好,它就是一个别名。(需要注意的是,引用主要是用在函数的参数调用中,一般不在函数的主体中用这个东西)
动态内存(在堆区内生成,且只能通过指针来使用:A:需要大量的数据;B:需要储存一组数,但是个数不确定)
C:这个不作介绍
C++:new与delete int ×p=new int [10/一个字母]/new int (10); delete []p;
内存泄漏和悬挂指针
内存泄漏:就是申请了一个动态的内存,但是这个指向这个内存的指针被更改,进而造成这个内存无法被继续使用。
悬挂指针:就是让指针指向了一个被释放的空间,再释放这个指针就会出现错误,因为不再存在可以被释放的内存。
接下来,讲我们的重点,指针与引用在使用过程中的方法:
函数:指针与函数:形参写为指针,而实参可以是数组名,地址,以及初始化后的指针(是指针名)。
引用与函数:形参写为引用,而实参直接写变量名。
常指针和指针常量:这个的诞生就是为了解决 原值,地址,以及更改方式的问题。
指针既可以改地方也可以改值(指针改,本身改)
引用不能改地址,但是可以改值(引用改,本身改)
常指针可以改地址,但是不可以通过指针来改,可以通过本身来改。语法:const int *p;
常引用不可以改地址,也不能通过引用来改,可以通过本身来改。语法:const int a&;
指针常量不可以改地址,但是可以通过地址和直接来改值。 语法:char *const p=&as;
指针函数与函数指针:如果一个函数的返回值是一个指针的话,我们称这种函数叫做指针函数;(这里有一个一撮点,不能返回局部变量的位置,因为它位于内存的栈区,会在自定义函数执行完之后被抹去,所以这时候,全局变量或者堆区就很好了)
函数指针是用来将几个相同类型的函数一次性的输出 语法:int (*p)(int ,int )int (int a,int b); p=ap1;
字符串 A:字符串可以用string库来体现
B:也可以用字符数组来体现 语法:char as[]=" "; 数组的好处在于可以直接的输入和输出,但是,不可以直接更改或者赋值
C:也可以字符指针来体现 char *p=" "; 指针的好处在于可以直接的更改或者赋值,或者输出但是,不可以去直接的输入
D.字符串的操作函数:字符串的长度:看上一个总结
字符串的复制:语法:char*strcpy(char *s1,const char *s2)将s2复制进s1中
按字符数赋值:语法 char *strncpy(char *s1,const char*s2,int n)复制的字符数
字符串的比较:语法 int strcmp(const char*s1,const char*s2) <0 =0 >0
字符串的连接: 语法 char*strcat(char*s1,const char*s2)
【在上述的函数中,我们可以看到,所有的原字符串都用的是常指针,所以不必担心原字符串被修改】
数组:A:指针与数组:
一维数组
数组名
访问的方式:数组名和指针名及其下标的偏移(值得注意的是,不可以用++来访问数组元素,因为数组名是常熟代表的是首地址)
二维数组
数组名:二维的数组名是指向一维数组的,不是指向的二维数组的元素。
访问的方式:*(p*+1)+1 根据上面的内容我们很容易看出来这个语法的合理性
emmm特别写一下,在二维数组用指针搞定的时候,记得命名指针的时候写的是char(类型名)(*p)[4](一维数组的维度)。
指针与结构体:原因:因为结构体的数据很多时,我们需要来将结构体放在堆内存中。
语法:A:struct as{int a;}=12;as *P=&12;
B:student *p=new as;(放在了堆内存中)
应用方法:p->a;
void类型的指针:void类型的指针可以指向各种数据的指针,可以被各种类型的指针赋值,但是,不能给其它的类型的指针赋值,因为不存在没有类型的数据,他的出现,多半是为了起一个中转站的作用。
下面我们来介绍一下这个中转站的流程:memcpy(void *dest,const void *scr ,size_t count )
例子:char *p=(char*)memcpy(a,b,10)
第二个用处是可以将char 类型的地址打出来,利用强制类型转化,进而将Char型的转化为void类型的,进而打出他的地址。
// ConsoleApplication3.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
using namespace std;
void swap(int *a, int *b)
{
int t;
t = *b;
*b = *a;
*a = t;
}
int main()
{
int *a, *b;
int c, d;
c = 3;
d = 4;
a = &c;
b = &d;
swap(a,b);
cout << *a << *b;
}
瞎贴两行代码
多说一句char与数字的运算就会导致数字变成Ascall码