[C++ Core] Explicación detallada de punteros y casos de referencia

1. Puntero

1.1 Conceptos básicos de punteros

El papel del puntero: Puede acceder a la memoria indirectamente a través de punteros.

  • El número de memoria se registra a partir de 0, generalmente representado por números hexadecimales
  • Las variables de puntero se pueden usar para almacenar direcciones

1.2 Definición y uso de variables puntero

Sintaxis de definición de variable de puntero:数据类型 * 变量名;

Ejemplo:

#include<iostream>
using namespace std;

int main() {
    
    

	//1、指针的定义
	int a = 10; //定义整型变量a
	
	//指针定义语法: 数据类型 * 变量名 ;
	int * p;

	//指针变量赋值
	p = &a; //指针指向变量a的地址
	cout << &a << endl; //打印数据a的地址
	cout << p << endl;  //打印指针变量p

	//2、指针的使用
	//通过*操作指针变量指向的内存
	cout << "*p = " << *p << endl;

	return 0;
}

La diferencia entre la variable de puntero y la variable ordinaria.

  • Las variables ordinarias almacenan datos,Las variables de puntero almacenan direcciones
  • La variable puntero puede operar el espacio de memoria apuntado por la variable puntero a través del operador "*". Este proceso se denomina desreferenciación.

Resumen 1: Podemos obtener la dirección de la variable a través del símbolo &
Resumen 2: Use el puntero para registrar la dirección
Resumen 3: Desreferenciar la variable del puntero, y puede manipular la memoria a la que apunta el puntero

1.3 Espacio de memoria ocupado por punteros

Pregunta: Un puntero también es un tipo de datos, entonces, ¿cuánto espacio de memoria ocupa este tipo de datos?

Ejemplo:

#include<iostream>
using namespace std;

int main() {
    
    

	int a = 10;

	int * p;
	p = &a; //指针指向数据a的地址

	cout << *p << endl; //* 解引用
	cout << sizeof(p) << endl;
	cout << sizeof(char *) << endl;
	cout << sizeof(float *) << endl;
	cout << sizeof(double *) << endl;

	return 0;
}

Resumen: todos los tipos de punteros tienen 4 bytes en un sistema operativo de 32 bits

1.4 Punteros nulos y punteros salvajes

Puntero nulo : la variable puntero apunta al espacio numerado 0 en la memoria

Propósito: inicializar variable de puntero

Nota: No se puede acceder a la memoria a la que apunta el puntero nulo

Ejemplo 1: puntero nulo

#include<iostream>
using namespace std;

int main() {
    
    

	//指针变量p指向内存地址编号为0的空间
	int * p = NULL;

	//访问空指针报错 
	//内存编号0 ~255为系统占用内存,不允许用户访问
	cout << *p << endl;

	system("pause");
	return 0;
}

Puntero salvaje : la variable del puntero apunta a un espacio de memoria ilegal

Ejemplo 2: puntero salvaje

#include<iostream>
using namespace std;

int main() {
    
    

	//指针变量p指向内存地址编号为0x1100的空间
	int * p = (int *)0x1100;

	//访问野指针报错 
	cout << *p << endl;

	system("pause");
	return 0;
}

Resumen: los punteros nulos y los punteros salvajes no son el espacio que solicitamos, así que no acceda a ellos.

1.5 puntero modificado const

Hay tres casos de puntero modificado const

  1. puntero modificado const — puntero constante
  2. const constante modificada — constante de puntero
  3. const modifica el puntero y modifica la constante

Ejemplo:

#include<iostream>
using namespace std;

int main() {
    
    

	int a = 10;
	int b = 10;

	//const修饰的是指针,指针指向可以改,指针指向的值不可以更改
	const int * p1 = &a; 
	p1 = &b; //正确
	//*p1 = 100;  报错
	
	//const修饰的是常量,指针指向不可以改,指针指向的值可以更改
	int * const p2 = &a;
	//p2 = &b; //错误
	*p2 = 100; //正确

    //const既修饰指针又修饰常量
	const int * const p3 = &a;
	//p3 = &b; //错误
	//*p3 = 100; //错误

	system("pause");
	return 0;
}

Consejos: vea si el lado derecho de const es un puntero o una constante, si es un puntero, es un puntero constante, si es una constante, es una constante de puntero

1.6 Punteros y matrices

Función: use punteros para acceder a los elementos de la matriz

Ejemplo:

#include<iostream>
using namespace std;

int main() {
    
    

	int arr[] = {
    
     1,2,3,4,5,6,7,8,9,10 };

	int * p = arr;  //指向数组的指针

	cout << "第一个元素: " << arr[0] << endl;
	cout << "指针访问第一个元素: " << *p << endl;

	for (int i = 0; i < 10; i++)
	{
    
    
		//利用指针遍历数组
		cout << *p << endl;
		p++;
	}

	system("pause");
	return 0;
}

1.7 Punteros y funciones

Función: use el puntero como un parámetro de función para modificar el valor del parámetro real

Ejemplo:

#include<iostream>
using namespace std;

//值传递
void swap1(int a ,int b)
{
    
    
	int temp = a;
	a = b; 
	b = temp;
}
//地址传递
void swap2(int * p1, int *p2)
{
    
    
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}

int main() {
    
    

	int a = 10;
	int b = 20;
	swap1(a, b); // 值传递不会改变实参

	swap2(&a, &b); //地址传递会改变实参

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	system("pause");
	return 0;
}

Resumen: si no desea modificar el parámetro real, páselo por valor; si desea modificar el parámetro real, páselo por dirección

1.8 Punteros, arreglos, funciones

Descripción del caso: encapsule una función y use la ordenación de burbujas para ordenar una matriz de enteros en orden ascendente

Por ejemplo matriz:int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };

Ejemplo:

#include<iostream>
using namespace std;

//冒泡排序函数
void bubbleSort(int * arr, int len)  //int * arr 也可以写为int arr[]
{
    
    
	for (int i = 0; i < len - 1; i++)
	{
    
    
		for (int j = 0; j < len - 1 - i; j++)
		{
    
    
			if (arr[j] > arr[j + 1])
			{
    
    
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}

//打印数组函数
void printArray(int arr[], int len)
{
    
    
	for (int i = 0; i < len; i++)
	{
    
    
		cout << arr[i] << endl;
	}
}

int main() {
    
    

	int arr[10] = {
    
     4,3,6,9,1,2,10,8,7,5 };
	int len = sizeof(arr) / sizeof(int);

	bubbleSort(arr, len);

	printArray(arr, len);

	system("pause");
	return 0;
}

Resumen: cuando el nombre de la matriz se pasa a la función como parámetro, se degenera en un puntero al primer elemento

2. Cita

2.1 Uso básico de las referencias

Rol: alias de la variable

gramática: 数据类型 &别名 = 原名

Ejemplo:

#include<iostream>
using namespace std;

int main() {
    
    

	int a = 10;
	int &b = a;

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	b = 100;

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	return 0;
}

2.2 Notas de cita

  • la referencia debe ser inicializada
  • Después de inicializar la referencia, no se puede cambiar

Ejemplo:

#include<iostream>
using namespace std;

int main() {
    
    

	int a = 10;
	int b = 20;
	//int &c; //错误,引用必须初始化
	int &c = a; //一旦初始化后,就不可以更改
	c = b; //这是赋值操作,不是更改引用

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;

	return 0;
}

2.3 Referencias como parámetros de función

Función: cuando una función pasa parámetros, puede usar la técnica de referencia para permitir que los parámetros formales modifiquen los parámetros reales

Ventajas: puede simplificar el puntero para modificar el parámetro real

Ejemplo:

#include<iostream>
using namespace std;

//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;
}

Resumen: el efecto de pasar parámetros por referencia es el mismo que pasar por dirección. La sintaxis para citar es más clara y sencilla.

2.4 Referencia como valor de retorno de la función

Rol: las referencias pueden existir como valores de retorno de funciones

NOTA: No devuelva referencias de variables locales

Uso: llamada de función como lvalue

Ejemplo:

#include<iostream>
using namespace std;

//返回局部变量引用
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;
	cout << "ref2 = " << ref2 << endl;

	return 0;
}

2.5 La naturaleza de las citas

Esencia: la esencia de la referencia se implementa dentro de C++ como una constante de puntero.

Explicar ejemplo:

#include<iostream>
using namespace std;

//发现是引用,转换为 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;
}

Conclusión: C ++ recomienda usar tecnología de referencia, porque la sintaxis es conveniente y la esencia de la referencia es una constante de puntero, pero el compilador realiza todas las operaciones de puntero por nosotros.

2.6 Referencias constantes

Rol: las referencias constantes se utilizan principalmente para modificar parámetros formales para evitar el mal uso

En la lista de parámetros de función, puede agregarparámetro modificado constante, para evitar que los parámetros formales cambien los parámetros reales

Ejemplo:

#include<iostream>
using namespace std;

//引用使用的场景,通常用来修饰形参
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;
}
``

おすすめ

転載: blog.csdn.net/cui_yonghua/article/details/131363075