C++复习中相关要点记录(二)

1、指针&地址

有一个介绍的很详细的博文可以参考:
C/C++指针详解之基础篇(史上最全最易懂指针学习指南!!!!)

  • 指针就是记录变量地址的工具。
  • C++中指针可以直接根据其指向的地址来存取变量,也可用于动态分配一维、二维数组等。
  • 使用指针也会造成内存访问问题。

(1)认识指针(Pointer)

  • 内存中每个字节都有一个内存编号,即地址(这一地址通常采用16进制数来表示)。
  • 我们不可能直接使用每个内存的地址,因此大多数高级语言提供声明变量和使用变量来解决这个问题;
  • 既然可以通过使用变量来访问,那我们何必非要去知道内存的地址呢?
  • C++使用指针的优点 这篇给出了回答,因为在某些时候使用指针真的会非常方便。
  • 其实,指针本身就是一种变量类型,存储的内容就是内存地址。通过指针变量,可以直接存取该指针指变量所指向的地址的内容。

(2)变量地址的存取

  • C++中定义变量之后,系统就会为其分配内存空间。
  • 需要使用某一数据时,存取那一地址的内存空间就可以了。
  • 如果想更清楚的了解这一变量所在内存的地址,就可以通过取地址符(&)来得到变量所在地址:
    &变量名

(3)指针变量的声明

  • 指针变量即:用来存储内存地址的变量。
  • 指针变量指向目标地址后,就可以通过移动指针,取得该地址所代表内存区块的数据值。
  • 因为指针也是一种变量,其命名规则与一般变量相同。
  • 程序声明指针时,内存分配情况与一般变量也相同。
  • 声明:
    int* p;
    int *p;
    意思是:声明一个指向int的指针类型变量,其名称为p;
    注意:p中存的是数据地址;而 *p存的才是数据本身;
  • !!!!指针变量必须指向合法地址(系统分配给程序的地址),或者指针变量在声明时先赋值为0或NULL;
  • 指针声明演示:类型* 指针变量;
    ① int* p=0; or int* p=NULL;
    ②int value =5; int* p = &value; // 变量value的地址放到p里,,也就是 * p=5
    ③int value=5; int* p=0; p=&value; //先让p存0(初始化),再指向value的地址;
    ④int* p=10; //z这种定义方式是错误的!!!
    ⑤int* p; *p=10; //也是错的,因为指针变量定义以后没有赋初值
    ⑥但是如果指针变量事先已经指向了定义或声明过的地址那 *p=10就是正确的(即改变哪个地址中的数据)。

(4)指针运算

int value = 10;
int* p =&value; // &value = 0x2004; 也就是变量value的内存地址的 16进制的2004
p++; //此时 p=2x2008; 因为int变量占4字节。

(5)多重指针

  • 由于指针变量是指向内存地址;
  • 而指针变量自己所占用的内存空间也拥有一个地址。
  • 可以声明“指针的指针”,即“指向指针变量的指针变量”或叫“多重指针”
    int num = 10;
    int* p=#
    int** p1 = &p;

(6)指针和数组

  • 在数组中,数组名就是指向该数组第一个元素的内存地址,或说是数组在内存中的其实地址。
  • 因此,已定义好的数组,其数组名就是一个指针变量;
  • int a[5]={0,5,2,3,4};
    a[0] = *a = 0;
    a[1] = *(a+1); = 5;
    a[2] = *(&a[2]);
  • int a[5]={0,5,2,3,4};
    int* p=a; 或 int* p = &a[0];

(7)指针和字符串

  • 之前说过的定义字符串的形式:
    用字符数组或指针形式:
    char a[]=“STRING”;
    或:
    char a[7]={‘S’,‘T’,‘R’,‘I’,‘N’,‘G’,’\0’};
  • 如同指针处理数组一样,c++中字符串也可以通过指针来声明和操作:
  • 用字符串指针变量指向字符串常量
    char *a = “STRING”; // *a = S; a = STRING;
    声明完成后,系统分配内存存储字符串常量,并设置指针变量 *p 来指向次变量的起始位置;

(8)指针数组

  • 类型 *数组名[元素数];
  • 二维数组的定义:
    char name[4][10]={“Tom”,“Mom”,“lihua”,“hanlei”};
  • 用数组指针:
    char *name[4] = {“Tom”,“Mom”,“lihua”,“hanlei”}; //此时 name[0] = Tom; *namae[0] = T;
    相当于定义了四个字符串常量,分别用四个字符串指针变量指向他们;

2、动态分配

(1)动态分配数组

  • C++可以用 new 和 delete运算符在程序运行期间动态分配与释放内存。
  • new运算符: 根据要求大小在内存分配足够空间,并返回分配内存的指针值,即内存地址。分配失败返回NULL。
  • 不用时用 delete删除分配的控件
  • 声明格式: 数据类型 *指针变量 = new 数据类型(初值); delete 指针名
    int *p = new int(77);
    float *p_f = new int; //未赋初值;
    delete p;
    delete p_f;
#include<iostream>
#include<cstdlib>

using namespace std;


int main()
{
	int *p1 = new int;
	int *p2 = new int;
	cout <<"被加数:"<<endl;
	cin>>*p1;
	cout<<"加数:"<<endl;
	cin>>*p2;
	
	cout<< *p1<<"+"<<*p2<<"="<<*p1+*p2;
	
	cout<<endl;
	
	delete p1;
	delete p2;
	
	system("pause");
	
	return 0; 

	
 }

(2)动态分配数组

  • 与动态分配变量相同,根据要求寻找合适的内存,并返回内存区段的起始地址。
  • 数据类型 *指针变量名 = new 数据类型[元素个数];
  • 分配动态数组,必须在中括号内预分配数组元素个数
  • 不用时delete [] 指针数组名; //固定格式 就这么写,中括号里没东西;

3、引用类型

  • 用来给变量、常数、或对象取别名;
  • 引用类型的重要特征:对变量或对象(B)取了别名(A)后,所有作用于A的运算效果同样会在B上产生。
  • 声明格式: 数据类型 &引用名称 = 初值;
    int j = 20;
    int &refj = j; //refj是j 的别名。

4、函数

  • 函数是一段程序语句的集合,并有一个名称代替次程序集合。函数可以视为一种独立的模块。需要某项功能时,只需要调用编写完成的函数即可。这样可以提高代码的可重用性,更容易维护。
  • c++中函数有两类:系统本身提供的标准函数、用户自定义函数。
  • 使用标准函数只需导入相关函数的头文件即可

(1)自定义函数

  • 格式:
    返回值类型 函数名(参数表)
    {
    函数体;
    return 返回值;
    }

(2)函数声明

  • 调用函数的程序代码在自定义函数之后,不需要声明。
  • 反之需要在调用函数的程序代码中对自定义函数进行声明。
  • 声明格式:
    返回值类型 函数名(数据类型 参1,数据类型 参2,…);

    返回值类型 函数名(数据类型 ,数据类型 ,数据类型,…);
int ADD_FUN(int a,int b);//函数声明
main(void){
	ADD_FUN(a,b);
	...
}

int ADD_FUN(int a, int b){....}

(3)!函数传值!

Ⅰ、传值调用:
  • 主程序调用自定义函数时,系统会为形参分配内存地址,并将实际参数的数值传递并复制给函数中对应的形参。
  • 在函数内的形参执行完毕后并不修改主函数中变量的内容。【这量个地方暂时先理解,也许有问题】
  • 传值调用时的函数声明和函数调用形式:
  • 函数声明
    返回值类型 函数名(数据类型 参1,数据类型 参2,…);

    返回值类型 函数名(数据类型 ,数据类型 ,数据类型,…);
  • 函数调用
    函数名(参1,参2,参3…);
Ⅱ、传址调用
  • 传址调用在 调用函数时并不会为形参分配实际的地址,而是将实参的地址直接传递给所对应的形参。
  • 由此,函数的形参将于所传递的实参共享同一地址,所以,函数内形参在执行完毕时将通过指针方式指向实参的变量地址,更改原先调用函数内的变量内容。【这一句意思就是,实参和形参共享同一地址,所以形参改变了,实参会随之改变】
  • 也就是说,C++是以 分配指针变量的形式参数来存放实际参数传入的变量地址,实际上也就是一种传递指针变量的功能。
  • 函数声明:
    返回值类型 函数名(数据类型 *参1,数据类型 *参2,…);

    返回值类型 函数名(数据类型 *,数据类型 *,数据类型 *,…);
  • 函数调用
    函数名(&参1,&参2,&参3…);
Ⅲ、参数默认值

可以在声明时为参数设置默认值,但是注意要放在右侧,因为C++编译程序会假设要省略的参数对应到参数行右侧(也就是,调用函数传参时实参个数可以小于形参个数,前提是右侧的几个形参设置了默认值)

Ⅳ、数组参数

之前说过数组的数组名就是该数组的首地址,所以传址调用的方式也可以应用在数组参数的传递上,可以直接使用传址调用的方式把一个数组传递个另一个函数【也就是,数组传递的时候传递的就是数组地址,或者说是指向数组地址的指针】

  • 在函数中该变数组内容,主程序中的数组内容也会随之改变。
  • 函数声明:
    返回值类型 函数名(数据类型 数组名[ ],数据类型 变量名,…){函数体}

    返回值类型 函数名(数据类型 *数组名,数据类型 变量名,…){函数体}
  • 函数调用:
    函数名(数组名,变量名,…);

(4)、指针返回值

返回值除了是一般类型以外,也可以是指针类型。

-函数声明:
返回值类型 *函数名(参数表){函数体}

5、函数的高级应用

函数指针这一块,还没完全理解,暂时不写,但是有一篇博文可以参考
C++函数指针学习

6、变量种类

  • 局部变量
    在一个函数内部定义的变量(包括函数形参),它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外是不能使用这些变量的,这种类型的变量就称为“局部变量”。局部变量存储在栈内存,在函数结束后自动销毁。
  • 全局变量
    在函数体外定义的变量,可以为本源文件中其它函数所公用,有效范围为从定义变量的位置开始到本源文件结束,这种类型的变量就称为“全局变量”。全局变量存储在静态存储区域(静态内存)。全局变量可以被同一工程项目中其他文件用extern声明后调用,对其每次进行修改都会被保存。
  • 静态全局变量:
    静态全局变量就是在原先的全局变量前面加上了static进行修饰。静态全局变量依然存储在静态存储区。跟全局变量最大的不同在于,静态全局变量不能被其他源文件使用,只能被本源文件使用,对其每次进行修改都会被保存。
  • ** 静态局部变量**
    静态局部变量就是在原先的局部变量前面加上了static进行修饰。静态局部变量是静态变量因此存储在静态存储区内,等到整个程序结束才会被销毁。但是它的作用域依然在函数体内部。但是自从静态局部变量被定义后,每次对其进行修改都会被保存下来。

7、函数重载问题

  • 同一函数名可以定义多个不同函数体,c++在调用函数时会根据形参个数或参数类型来决定调用的是哪个函数。
  • 在c语言中就需要钉以不同函数名(Fun1,Fun2…)
  • 函数重载规则:
    (1)函数名必须相同。
    (2)各重载函数间的参数行类型与个数不能完全相同。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值