Notas de gramática de C++: función en línea, palabra clave automática, nullptr

Tabla de contenido

1. Funciones en línea

1. Revisar la "función macro" en lenguaje C

2. Funciones en línea 

3. Características de las funciones en línea

 2. Palabra clave automática de C++

1. El concepto básico de auto

2. Precauciones para el uso automático

3. Donde no se puede usar auto

 3. punto nulo en C++ 11


1. Funciones en línea

1. Revisar la "función macro" en lenguaje C

Primero da un código simple:

int Add(int left, int right)
{
	return left + right;
}

int main()
{
	int ret = 0;
	ret = Add(1, 2);
	return 0;
}

Ir al código ensamblador:

 

 

 

Se puede ver que para realizar una adición simple, se deben ejecutar muchas instrucciones de ensamblaje para llamar a la función Agregar, y se deben ejecutar saltos de instrucciones para llamar a la función (y se debe abrir espacio de marco de pila para la función en el área de la pila ), si la función Agregar se repite una gran cantidad de Si se usa, consumirá una gran parte del rendimiento del sistema . Por lo tanto, para mejorar la eficiencia de ejecución del programa en lenguaje C, a menudo usamos macros en lugar de funciones simples similares (tenga en cuenta que están limitadas a funciones cortas y no recursivas) :

#define Add(X,Y) ((X)+(Y))

int main()
{
	int ret = 0;
	ret = Add(1, 2);
	return 0;
}

La función de la macro es equivalente al reemplazo de la declaración de código. La macro en el segmento de código anterior es reemplazar la declaración en forma de Add(X,Y) con ((X)+(Y)). Este reemplazo el proceso se encuentra en la etapa de preprocesamiento completada.

Después de usar la sustitución de macros, ejecute el fragmento de código anterior para ir al desmontaje:

 

Se puede ver que el uso de macros en lugar de funciones cortas, no recursivas (y muy utilizadas) puede mejorar el rendimiento del programa hasta cierto punto.

Sin embargo, dado que la esencia de las macros es el reemplazo de código, a veces el código se vuelve confuso y difícil de mantener , y el uso de macros en sí es propenso a errores . C++ proporciona un mecanismo de sintaxis similar: funciones en línea en lugar de macros.

2. Funciones en línea 

La función modificada por la palabra clave en línea se denomina función en línea . Al compilar, el compilador de C++ expandirá la función llamada en una serie de instrucciones de ensamblaje en la instrucción de ensamblaje (instrucción de llamada) que llama a la función en línea y realizará la función llamada en el espacio de marco de pila de la función principal.La función de funciones de llamada (similar al reemplazo de macro, pero no completado en la etapa de preprocesamiento), el sistema no necesita crear un marco de pila de función para la función llamada, mejorando así la eficiencia del programa operación.

Use el ejemplo anterior para ilustrar, antes de usar en línea para modificar la función Agregar :

 

Después de modificar la función Add con inline :

 

Se puede ver que el sistema no crea un marco de pila de funciones para la función Agregar en línea , ni ejecuta ningún salto de instrucción, y el rendimiento del programa ha mejorado. (Pero tenga en cuenta que el cuerpo de la función de la función Agregar (incluido su segmento de instrucción) aún se almacena en el área constante de solo lectura tal como está , pero el compilador "mueve" las instrucciones necesarias en el cuerpo de la función al segmento de instrucción del La función principal durante la compilación reemplaza la instrucción de llamada ).

3. Características de las funciones en línea

(1) La función en línea es una forma de intercambiar espacio por tiempo . Si el compilador trata la función como una función en línea, en la etapa de compilación, reemplazará la instrucción de llamada que llama a la función con un segmento de instrucción que puede completar la función función _

Defecto: puede aumentar el tamaño del archivo de destino ( las instrucciones de ensamblaje ocupan memoria y el compilador reemplaza la instrucción de llamada con una serie de segmentos de instrucción, lo que aumentará la cantidad total de instrucciones en el archivo) .

Ventajas: Menos sobrecarga del sistema para las funciones de llamada, lo que mejora la eficiencia de ejecución del programa.

(2) en línea solo puede modificar algunas funciones no recursivas con funciones simples y segmentos de código cortos. Si se usa en línea para modificar una función compleja, el compilador ignorará automáticamente la palabra clave en línea al compilar, por lo que en línea es solo para el compilador . palabra clave en lugar de un comando a ser aplicado. 

(3) No se recomienda que las funciones en línea (funciones modificadas por en línea) separen su declaración y definición (simplemente use la definición, la definición en sí también es un tipo de reputación), la separación dará lugar a errores de enlace. Debido a que se usa en línea, la instrucción de llamada se reemplaza cuando se llama a la función. Sin la instrucción de llamada, el enlazador no puede vincular el segmento de instrucción del cuerpo de la función. ( Entonces, las funciones en línea generalmente se definen en el mismo archivo fuente que la función principal )

 2. Palabra clave automática de C++

1. El concepto básico de auto

En C++ 11, auto se usa para definir variables. El tipo de la variable definida por auto está determinada por el tipo del valor en el lado derecho de la definición de variable y el signo igual de la instrucción de inicialización . Auto se usa como tipo indicador para indicar el compilador.La variable declarada por auto debe ser inferida por el compilador en tiempo de compilación. Por ejemplo:

int TestAuto()
{
	return 10;
}

int main()
{
	int a = 10;
	auto b = a;                   //变量b c d的类型由编译器根据等号右边的值自动识别
	auto c = 'a';                 //typeid(b).name() 是一个可以返回类型名字符串的方法
	auto d = TestAuto();
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;
	return 0;
}

En la programación compleja orientada a objetos,  a veces nos resulta difícil determinar de qué tipo será el valor de retorno de una expresión , en este caso, la variable declarada por auto puede usarse para recibir el valor de la expresión . A veces, en la programación de C++, el valor de la expresión es un valor de tipo autodefinido muy complejo En este momento, la variable declarada por auto también se puede usar para recibir el valor de la expresión .

Por ejemplo, el siguiente escenario:

#include <iostream>
#include <time.h>
#include <string>
#include <map>

using std::cout;
using std::endl;


int main()
{
	std::map<std::string, std::string> m{ { "apple", "苹果" }, 
		                                  { "orange","橙子" },
	                                      {"pear","梨"} 
	                                     };
	
	auto it  = m.begin();         用auto声名的变量it来接收表达式的返回值
	
	while (it != m.end())
	{
		//....
	}
	return 0;
}

El std::map<std::string, std::string> en el segmento de código anterior es un tipo complejo, y el valor de retorno de m.begin() puede ser recibido por la variable denominada auto, lo cual es muy conveniente .

typedef (redefinición de tipo) también puede simplificar el código anterior, pero cuando typedef se usa para redefinir el tipo de puntero y declarar variables, const no se puede usar para proteger el espacio de memoria al que apunta el puntero .

Por ejemplo:

typedef char* pstring;
int main()
{
    const pstring p1=NULL;
    return 0;
}

Por lo tanto, el uso de typedef también es limitado, mientras que el uso de auto es más conveniente y flexible.

2. Precauciones para el uso automático

(1) Cuando se usa auto para definir una variable , debe inicializarse En la etapa de compilación, el compilador necesita deducir el tipo real de auto de acuerdo con la expresión de inicialización

(2) auto no es una declaración de "tipo", sino un "marcador de posición" cuando se declara el tipo . El compilador reemplazará auto con el tipo real de la variable en el momento de la compilación

(3) Cuando se usa auto para declarar un tipo de puntero, no hay diferencia entre usar auto y auto*, pero cuando se usa auto para declarar un tipo de referencia, debe agregar
&,

por ejemplo:

int main()
{
    int x = 10;
    auto a = &x;
    auto* b = &x;           a,b的类型最终是一样的
    auto& c = x;            想定义引用必须在auto后面加上&
    cout << typeid(a).name() << endl;
    cout << typeid(b).name() << endl;
    cout << typeid(c).name() << endl;
    *a = 20;
    *b = 30;
    c = 40;
    return 0;
}

(4) Al declarar varias variables en la misma línea, estas variables deben ser del mismo tipo ; de lo contrario, el compilador informará un error, porque el compilador en realidad solo deduce el primer tipo y luego usa el tipo deducido para definir otras variables.

Por ejemplo:

void TestAuto()
{
	auto c = 3, d = 4.0;   该行代码会编译失败,因为c和d的初始化表达式类型不同
}

3. Donde no se puede usar auto

1. auto no se puede utilizar como parámetro de función

2. auto no se puede usar directamente para declarar una matriz

Por ejemplo:

void TestAuto()
{
    int a[] = {1,2,3};
    auto b[] = {4,5,6};   无法通过编译
}

 3. punto nulo en C++ 11

En una buena práctica de programación C/C++, es mejor dar a la variable un valor inicial adecuado al declarar una variable, de lo contrario, pueden ocurrir errores inesperados, como punteros no inicializados. En lenguaje C, si un puntero no tiene señal legal, básicamente lo inicializamos de la siguiente manera:

void TestPtr()
{
    int* p1 = NULL;
    // ……
}

NULL es en realidad una macro, y NULL se reemplazará con un número entero 0 en tiempo de compilación , por lo que usar NULL no es de tipo estricto y puede causar errores en algunos casos extremos.

Entonces, C++ 11 introdujo nullptr como una nueva palabra clave para representar el valor nulo del puntero.

Para mejorar la robustez del código, se recomienda utilizar nullptr al representar el valor nulo del puntero.

void TestPtr()
{
    int* p1 = nullptr;
    // ……
}

 

 

Supongo que te gusta

Origin blog.csdn.net/weixin_73470348/article/details/128742883
Recomendado
Clasificación