C++指针概念、指针变量作为函数参数进行传参

指针定义

p是一个指针,代表的是存储的值的地址
*p是存储在地址中的值

//创建变量a,将值1存储在该变量中
int a = 1;
//创建变量pa,将变量a的地址存储在pa中
int* pa = &a;
//强调*p是一个int类型的值——C程序员
int *p;
//强调int*是一种类型——C++程序员
int* p;

指针变量进行函数传参——交换两个变量的值

函数的参数不仅可以是整数、小数、字符等具体的数据,还可以是指向它们的指针。

指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着函数的结束而被销毁。

像数组、字符串、动态分配的内存等都是一系列数据的集合,没有办法通过一个参数全部传入函数内部,只能传递它们的指针,在函数内部通过指针来影响这些数据集合。

……
startTest();
……

void MainWindow::startTest()
{
    
    
    qDebug() << "asd";

    int a = 1;
    int b = 2;

    swap(a, b);

    qDebug() << a << b;
}

//Qt中除了构造函数和析构函数,都要加上void或double的类型
void MainWindow::swap(int a, int b)
{
    
    
    qDebug() << a << b;
    
    int temp = a;
    a = b;
    b = temp;
    
    qDebug() << a << b;
}
asd
1 2
2 1
1 2

a、b 的值并没有发生改变,交换失败。

生存周期不一样,以函数里定义的局部变量,在函数运行完之后就会结束,在swap函数中确实可以交换数据,但是无法在函数外部进行显示其变化

这是因为 swap() 函数内部的 a、b 和 main() 函数内部的 a、b 是不同的变量,占用不同的内存,它们除了名字一样,没有其他任何关系

swap() 交换的是它内部 a、b 的值,不会影响它外部(main() 内部) a、b 的值。

……
 pStartTest();
……
 
void MainWindow::pStartTest()
{
    
    
    qDebug() << "asd";
    
    int a = 1;
    int b = 2;
    
	//调用 pSwap() 函数时,将变量 a、b 的地址分别赋值给 p1、p2(都是地址)
    pSwap(&a, &b);
    
    qDebug() << a << b;
}

void MainWindow::pSwap(int* p1, int* p2)
{
    
    
    qDebug() << *p1 << *p2;
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;

    qDebug() << *p1 << *p2;
}

函数运行结束后虽然会将 p1、p2 销毁,但它对外部 a、b 造成的影响是“持久化”的,不会随着函数的结束而“恢复原样”。

asd
1 2
2 1
2 1

指针变量进行函数传参——数组作函数参数

#include <stdio.h>

//C++系列专属
#include <iostream>
using namespace std;

int max(int *intArr, int len) 

//int类型的可以不用声明,但是void类型必须声明
int max(int *intArr, int len) {
    
    
	int i, maxValue = intArr[0];  //假设第0个元素是最大值
	for (i = 1; i < len; i++) {
    
    
		if (maxValue < intArr[i]) {
    
    
			maxValue = intArr[i];
		}
	}
	return maxValue;
}

int main() {
    
    
	int nums[6], i;
	int len = sizeof(nums) / sizeof(int);//可以得到长度

	//读取用户输入的数据并赋值给数组元素
	for (i = 0; i < len; i++) {
    
    
		//scanf_s("%d", nums + i);
		//不可以使用nums++,是因为是常量指针
		cin >> nums[i];//常量指针
	}

	//printf("Max value is %d!\n", max(nums, len));
	//max函数的返回值是int类型的值,可以直接写
	cout << max(nums, len);//nums是数组变量名,也就是数组的首地址

	system("pause");
	return 0;
}
12 55 30 8 93 27(enter)
Max value is 93!

参数 intArr 仅仅是一个数组指针,在函数内部无法通过这个指针获得数组长度,必须将数组长度作为函数参数传递到函数内部(必须)
数组 nums 的每个元素都是整数,scanf() 在读取用户输入的整数时,要求给出存储它的内存的地址,nums+i就是第 i 个数组元素的地址

数组形参的定义

以下的三种方式都是可以的,都是需要传递数组的长度的;

不管是int intArr[6]还是int intArr[]都不会创建一个数组出来,编译器也不会为它们分配内存,实际的数组是不存在的,它们最终还是会转换为int *intArr这样的指针

int intArr[6]这种形式只能说明函数期望用户传递的数组有 6 个元素,并不意味着数组只能有 6 个元素,真正传递的数组可以有少于或多于 6 个的元素。

需要强调的是,不管使用哪种方式传递数组,都不能在函数内部求得数组长度,因为 intArr 仅仅是一个指针,而不是真正的数组,所以必须要额外增加一个参数来传递数组长度。

//int max(int intArr[], int len){
    
    
//int max(int intArr[6], int len){
    
    
int max(int *intArr, int len) {
    
    
	int i, maxValue = intArr[0];  //假设第0个元素是最大值
	for (i = 1; i < len; i++) {
    
    
		if (maxValue < intArr[i]) {
    
    
			maxValue = intArr[i];
		}
	}
	return maxValue;
}

函数传参本质上是一次赋值的过程,赋值就是对内存进行拷贝。所谓内存拷贝,是指将一块内存上的数据复制到另一块内存上。

对于像 int、float、char 等基本类型的数据,它们占用的内存往往只有几个字节,对它们进行内存拷贝非常快速。

而数组是一系列数据的集合,数据的数量没有限制,可能很少,也可能成千上万,对它们进行内存拷贝有可能是一个漫长的过程,会严重拖慢程序的效率,为了防止技艺不佳的程序员写出低效的代码,C语言没有从语法上支持数据集合的直接赋值。

除了C语言,C++、Java、Python 等其它语言也禁止对大块内存进行拷贝,在底层都使用类似指针的方式来实现。

猜你喜欢

转载自blog.csdn.net/qq_43641765/article/details/112449859
今日推荐