指针和引用
一、指针定义:
在32位操作系统下 ,指针只占4个空间字节大小
在64位操作系统下 ,指针只占8个空间字节大小
**空指针用于给指针变量进行初始化,不可以进行访问
int *p=NULL;**
#include<iostream>
using namespace std;
int mian()
{
//1.定义指针
int a = 10; //整型变量
int *p;
//int *p = &a; **也可以这样定义**
//野指针 : int *p = (int *)0x100
//在程序中尽量避免野指针的出现
//指针变量指向变量a的地址
p = &a;
cout << "&a=" << &a<<endl;
cout << p << endl;
*p = 1000; //代表解引用
cout << "*p=" << *p << endl;
system("pause");
return 0;
}
引用作函数参数:
1. 值传递
(形参不会修饰实参)
(形参(函数体里的参数)
可以发生改变。但是实参永远不会发生变化)
void mySwap01(int a, int b) {
int temp = a;
a = b;
b = temp;
}
2. 地址传递
(形参会修饰实参)
void mySwap02(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
3. 引用传递
(形参会修饰实参)
void mySwap03(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 10;
int b = 20;
mySwap01(a, b);
cout << "a:" << a << " b:" << b << endl;
mySwap02(&a, &b);
cout << "a:" << a << " b:" << b << endl;
mySwap03(a, b);
cout << "a:" << a << " b:" << b << endl;
system("pause");
return 0;
}
引用作函数返回值
作用:引用是可以作为函数的返回值存在的
注意:不要返回局部变量引用
用法:函数调用作为左值
//返回局部变量引用
int& test01() {
int a = 10; //局部变量
return a;
}
//返回静态变量引用
int& test02() {
static int a = 20; //静态变量,存在全局区
return a;
}
int main() {
//不能返回局部变量的引用
int& ref = test01();
cout << "ref = " << ref << endl;
cout << "ref = " << ref << endl;
//如果函数做左值,那么必须返回引用
int& ref2 = test02();
cout << "ref2 = " << ref2 << endl;
cout << "ref2 = " << ref2 << endl;
test02() = 1000;
cout << "ref2 = " << ref2 << endl; //输出还是1000
cout << "ref2 = " << ref2 << endl;
system("pause");
return 0;
}
引用的本质
本质:引用的本质在c++内部实现是一个指针常量.
讲解示例:
//发现是引用,转换为 int* const ref = &a;
void func(int& ref){
ref = 100; // ref是引用,转换为*ref = 100
}
int main(){
int a = 10;
//自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改
int& ref = a;
ref = 20; //内部发现ref是引用,自动帮我们转换为: *ref = 20;
cout << "a:" << a << endl;
cout << "ref:" << ref << endl;
func(a);
return 0;
}
常量引用
作用:常量引用主要用来修饰形参,防止误操作
在函数形参列表中,可以加const修饰形参,防止形参改变实参
//引用使用的场景,通常用来修饰形参
void showValue(const int& v) {
//v += 10;
cout << v << endl;
}
int main() {
//int& ref = 10; 引用本身需要一个合法的内存空间,因此这行错误
//加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp;
const int& ref = 10;
//ref = 100; //加入const后不可以修改变量
cout << ref << endl;
//函数中利用常量引用防止误操作修改实参
int a = 10;
showValue(a);
system("pause");
return 0;
}
二、const 修饰指针
(1).常量指针
const int * p = &a;
* p = 20 //错误 指针指向的值不可以改变
p = &b //正确,指针指向可以改变
(2).指针常量
int * const p = &a;
* p = 20 //正确 指针指向的值可以改变
p = &b //错误 指针的指向不可以改变
【常量指针和指针常量指向的区别】
#include<iostream>
using namespace std;
int mian()
{
//1.const 修饰指针 常量指针
int a;
int b;
const int * p1 = &a;
//*p1 = 20;错误 指针指向的值不可以改变
p1 = &b;
//2.const 修饰常量 指针常量
int * const p2 = &a;
*p2 = 100;
//p2 = &b; 错误 指针的指向不可以改变
//3..const 修饰指针和常量
//都不可以修改了就
system("pause");
return 0;
}
三、指针运算
(1).赋值运算
int c = 16,d = 20;
float x = 26.4f, y = 56.2f;
int *pc, *pd = &d; // 使pb指向变量b;
float *px, *py = NULL; //使py的值为0;
px = &x; //使指针px指向变量x;
pc = pd; //两个指针变量赋值相等,并使他们指向同一个内存单元;
(2).算数运算
int x, y, *p = &y;
x = *p++; //x=*(p++),x的值就是y;
x = *++p;//x=*(++p),先进行自增运算,再进行赋值运算;
x == (*p)++;// 就是y++;
x = ++(*p); //就是y+1
(3).指针运算案例
【输入两个整数,用指针将它们从大到小的顺序输出;】
#include<iostream>
using namespace std;
int main()
{
int a, b, t;
int *p = &a, *q = &b;
cout << "请输入两个数:" << endl;
cin >> a >> b;
if (a < b)
{
t = *p; //交换值
*p = *q;
*q = t;
}
cout << "交换后的数字为:" << endl;
cout << a << "\t" << b << endl;
cout << *p << "\t" << *q << endl;
system("pause");
return 0;
}
四、指针和数组
【指针和数组比较】:
(1).指针和一维数组
数组元素的指针:
p=a 跟 p=&a[0]是等价的;
【利用指针访问数组元素读取数组元素】;
#include<iostream>
using namespace std;
int main()
{
//利用指针访问数组元素读取数组元素;
//先定义一个数组;
int app[10] = { 1,2,3,4,5,6,7,8,9,10 }, *p2 = app;
int bpp[10],*p1=bpp;
//随机的数组元素:
cout << "输出随机的数组元素2x 的值" << endl;
for (int j = 0; j < 10; j++)
{
*p1++ = 2 * (j + 1); //就是等价于*(p++)=2 * (j + 1)
}
for (p1 = bpp; p1 < bpp + 10;)
{
cout << *p1++ << endl;
}
cout << "输出指定数组的元素app[10]:" <<endl;
//指定数组的元素
for (int i = 0; i < 10;i++)
{
//cout << app[i]<< endl;
//利用指针访问数组 app[10];
cout << *p2 << endl;
p2++;
}
system("pause");
return 0;
}
(2).指针与二维数组
与一维数组不同的是:除了有元素的地址外,还有标识各行起始位置的行首地址
指针就是间接的访问数据,首先取得指针的内容,把它作为地址,然后从这个地址提取数据。通常用于动态数据结构;
【用指向元素的指针变量生成由自然数1-25组成的5*5方阵】
#include<iostream>
using namespace std;
int main()
{
int a[5][5];
int *jp = *a; //就是代表a[0][0]的地址;
int i, j;
for (i = 1; jp < *a + 25; jp++) //*a + 25 遍历数组的所有元素并对其进行赋值;
{
*jp = i++;
//cout << *jp;
if ((i - 1) % 5==0)
cout << endl;
}
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
cout << a[i][j]<<" ";
cout<<endl;
}
system("pause");
return 0;
}
五、指针与一维数组(指向整个一维数组)
int b[3][5]={12,45,46,14,48,46,48,87,56,47,16,38,92,75,73}
int (*p)[5]=b;
*表示这是一个指针变量;
说明这种指针变量指向的是整个一维数组
p+i;p[i];*p+i 就表示b[i][0];
*(p+i)+j;p[i]+j;&p[i][j] 就表示b[i][j];
【输出数组中每个元素的首地址】
#include<iostream>
using namespace std;
int main()
{
int b[3][5] = {12,45,46,14,48,46,48,87,56,47,16,38,92,75,73};
int(*p)[5] = b; //p是一个行指针变量;*p+i和p[i]是列指针;
//输出每行的首地址 p+i;p[i];*p+i 就表示b[i][0];
cout << "输出每行的首地址(p+i):" << endl;
for (int i = 0; i < 3; i++)
{
cout << *(p + i) << "---"; //p+i;*(p+i)都代表每行的首地址
}cout << endl << endl;
cout << "输出每行的首地址p[i]:" << endl;
for (int i = 0; i < 3; i++)
{
cout << p[i] << "---";
}cout << endl << endl;
//输出数组每个元素的地址 *(p+i)+j; ;&p[i][j] 就表示b[i][j];
cout << "输出数组每个元素的地址 *(p+i)+j:" << endl;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
cout << *(p + i) + j << "---";
}
cout << endl;
}
cout << endl;
cout << "输出数组每个元素的地址 p[i]+j:" << endl;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
cout << p[i] + j << "---";
}
cout << endl;
}
cout << endl;
//输出数组每个元素的值;
cout << "输出数组每个元素的值(普通方法)" << endl;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
cout <<p[i][j] << "---";
}
cout << endl;
}
cout << endl;
cout << "输出数组每个元素的值(指针方法)" << endl;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
cout <<*(*(p+i)+j) << "---";
}
cout << endl;
}
system("pause");
return 0;
}
/*
程序输出:
输出每行的首地址(p+i):
001AFCF4---001AFD08---001AFD1C---
输出每行的首地址p[i]:
001AFCF4---001AFD08---001AFD1C---
输出数组每个元素的地址 *(p+i)+j:
001AFCF4---001AFCF8---001AFCFC---001AFD00---001AFD04---
001AFD08---001AFD0C---001AFD10---001AFD14---001AFD18---
001AFD1C---001AFD20---001AFD24---001AFD28---001AFD2C---
输出数组每个元素的地址 p[i]+j:
001AFCF4---001AFCF8---001AFCFC---001AFD00---001AFD04---
001AFD08---001AFD0C---001AFD10---001AFD14---001AFD18---
001AFD1C---001AFD20---001AFD24---001AFD28---001AFD2C---
输出数组每个元素的值(普通方法)
12---45---46---14---48---
46---48---87---56---47---
16---38---92---75---73---
输出数组每个元素的值(指针方法)
12---45---46---14---48---
46---48---87---56---47---
16---38---92---75---73---
*/
六、指针数组
指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。
数组指针:首先它是一个指针,它指向一个数组。在32 位系统下永远是占4 个字节,至于它指向的数组占多少字节,不知道。它是“指向数组的指针”的简称。
*格式:类型名 数组名[数组长度]
【按照数组元素的大小对数组元素地址进行排序(冒泡排序)】
//sort 排序函数
#include<iostream>
using namespace std;
void sort(int *x[],int n) //按照指针数组x所指向变量的值的大小,对指针数组x进行排序;
{
int t;
for (int i = 0; i < n - 1;i++) //冒泡排序
{
for (int j = 0; j < n - i - 1; j++) //相邻元素的比较
{
if (*x[j] > *x[j + 1])
{
t = *x[j]; //*x[j]为元素值;
*x[j] = *x[j + 1];
*x[j + 1] = t;
}
}
}
}
int main()
{
int i;
int a[10] = { 12,45,78,89,56,23,14,25,36,47 };
//先声明指针数组;
int *b[10];
//将a数组里的地址赋值给b[i];
for (int i = 0; i < 10; i++)
{
b[i] = &a[i]; //&a[i]为a[10]中的每一个地址;
}
sort(b, 10); //调用函数就行排序
cout << "输出排序后的序列:" << endl;
for (i = 0; i < 10; i++)
{
cout << *b[i] << " ";
}
system("pause");
return 0;
}
七、指针与函数
利用指针做函数的参数,可以改变
【值传递与地址传递 输出数字】
#include<iostream>
using namespace std;
//1.值传递:如果主函数中定义了形参的值,那么相应的实参是不受影响的;
void swap1(int x, int y)
{
int t;
t = x;
x = y;
y = t;
cout << "x=" << x << endl;
cout << "y=" << y << endl;
}
//2.地址传递:实参不会改变;
void swap2(int *p1, int *p2)
{
int t;
t = *p1;
*p1 = *p2;
*p2 = t;
cout << "地址传递的结果为:" << endl;
cout << "a1=" << *p1 << endl;
cout << "b1=" << *p2 << endl;
}
//引用传递:
int main()
{
int a = 99;
int b = 11;
swap1(a, b);
swap2(&a, &b);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}
/*
程序输出:
x=11
y=99
地址传递的结果为:
a=11
b=99
a=11
b=99
*/
【调用排序函数对数组里的元素进行排序】
#include<iostream>
using namespace std;
//声明冒泡排序函数;
void sort(int *arr, int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int t;
t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
}
}
}
}
//也可以创建一个打印函数的数组;
void print(int *arr, int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}
int main()
{
//创建一个数组;
int arr[10] = { 12,45,78,89,56,23,14,25,36,39 };
//求数组长度;
int len = sizeof(arr) / sizeof(arr[0]);
//调用函数,实现冒泡排序;
sort(arr, len);
//打印排序后的数组;(也可以用调用函数的形式打印)
for (int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
cout << "用调用函数的形式输出为:" << endl;
print(arr, len);
system("pause");
return 0;
}
一起加油吧!