Fundamentos de la estructura de datos y el algoritmo (Wang Zhuo) (8) Anexo: explicación detallada de cómo usar el nuevo

Tabla de contenido

parte 1:

El uso de new en C++ (pero solo) es el siguiente (varios usos):

1: nuevo<tipo de datos>

2: nuevo<tipo de datos>(<valor inicial>)

3: nuevo<tipo de datos>[<número de unidades de memoria>]

Adjunto: parte 1

Adjunto: parte 2

Parte de la diferencia entre no escribir nuevo y usar nuevo:

parte 2:

parte 3:


parte 1:

El uso de new en C++ (pero solo) es el siguiente (varios usos):

1: nuevo<tipo de datos>

distribuir:

El tipo especificado, el tamaño es 1, el espacio de memoria;

	int *i = new int;
	//注意!如果写:
	//int i = new int;
	//不行,会报错

2: nuevo<tipo de datos>(<valor inicial>)

distribuir:

El tipo especificado, el tamaño es 1, el espacio de memoria; inicialice la variable con el valor entre paréntesis

	int *i = new int(2);

3: nuevo<tipo de datos>[<número de unidades de memoria>]

distribuir:

El tipo especificado, el tamaño es (el número en el cuadro) n, el espacio de memoria

Use el número n en el cuadro: el tamaño del espacio de inicialización (número de elementos de matriz)

memoria en forma de matriz

	int* i = new int[5];
	char* i = new char[5];

Adjunto: parte 1

Defina una variable de matriz multidimensional o un objeto de matriz, generando un puntero al primer elemento de la matriz

Tipo devuelto: contiene todas las dimensiones excepto la dimensión más a la izquierda

int *p1 = new int[10];   
devuelve un puntero a int type int*  

int (*p2)[10] = new int[2][10]; 
devuelve una matriz unidimensional que apunta a int[10], puntero int (*)[10]

int (*p3)[2][10] = nuevo int[5][2][10];     

Devuelve un puntero a una matriz bidimensional int[2][10] de este tipo int (*)[2][10]

 Pero necesitamos recordatorios especiales aquí (atención):

Aquí no importa cuál de las tres situaciones anteriores

Variables en el lado izquierdo de una declaración de asignación en una nueva declaración, sin importar qué:

¡Esta variable es, solo puede ser, debe ser un puntero! ! !

Y no es como en la estructura de datos detrás de nosotros

Fundamentos de la estructura de datos y el algoritmo (Wang Zhuo) (5): operaciones más complejas en listas enlazadas (únicas)_宇-Blog de Yu-Blog de CSDN

Como se menciona en él, el tipo de espacio abierto puede tener variables de este tipo directamente en el lado izquierdo de la instrucción de asignación.

¡Solo se pueden colocar punteros a ese tipo a la izquierda! ! !


original:

Puntos:

acerca de

L= nuevo Lnodo;

De hecho, creo que es realmente superfluo:

Cuando el sistema comenzó con el parámetro LinkList &L, ¿no se le asignó de antemano el espacio de memoria de L por defecto? ¿Por qué sigue trabajando duro aquí?

Además, ¿dónde creó espacio el formato de L= new Lnode? ? ?

Aprendí sobre el uso de nuevo, solo definiendo punteros para asignar nuevo espacio, como:

   Lnodo* p = nuevo Lnodo;

Pero como está disponible aquí, también debemos recordar:

L= nuevo Lnodo;

Ahora mismo:

<Primera dirección del espacio abierto> = new <Tipo de datos del espacio abierto>

Formato (recuerde agregar automático si no se ha definido antes)

Finalmente, después de profundizar en el uso y el formato de new, descubrimos que este no es el caso:

No porque signifique que L es una tabla, pero hay un nuevo formato como supusimos

Es porque la lista de enlaces &L delante del encabezado de la tabla muestra que originalmente es un puntero y aún pertenece a la especificación de uso original.

Es decir, si hemos definido la variable antes (cuando se pasa el parámetro formal), cuando abramos espacio más tarde

No (y no podemos) (re)declarar el tipo de la variable


Adjunto: parte 2

El formato general de nueva creación dinámica de una matriz bidimensional en C++:

TIPO (*p)[N] = nuevo TIPO [][N];

El tipo de p: TYPE*[N]; es decir: un puntero a una matriz con N columnas de elementos

Sin especificar el número de columnas de una matriz (crea una matriz bidimensional):

 int **p;

ejemplo:

	int **p = new int* [10]; 
	//int*[10]表示一个有10个元素的指针数组
	
	for (int i = 0; i != 10; ++i)
		p[i] = new int[5];


Parte de la diferencia entre no escribir nuevo y usar nuevo:

La recepción del puntero es necesaria , se inicializa en un lugar y se usa en varios lugares

Como se dijo anteriormente:

Variables en el lado izquierdo de una declaración de asignación en una nueva declaración, sin importar qué:

¡Esta variable es, solo puede ser, debe ser un puntero! ! !

Se refiere a lo que estamos hablando aquí, el puntero usado para recibir

Necesita borrar para destruir


new crea objetos directamente usando el espacio de almacenamiento dinámico

Y el parcial no usa new para definir el objeto para usar el espacio de pila


El nuevo puntero de objeto tiene una amplia gama de usos, como valores de retorno de función, parámetros de función, etc.


Las llamadas frecuentes no son adecuadas para las nuevas, al igual que las nuevas aplicaciones y la liberación de memoria.

ejemplo:

Crear objetos con nuevo: (pTest: usado para recibir punteros de objetos)

	int* pTest = new int();
	delete pTest;

Crear objetos sin nuevos: (definir directamente con declaración)

	int mTest;

Cree objetos sin nuevos y no necesite liberarlos manualmente después de su uso (función de eliminación de escritura)

Los destructores de clases se ejecutan automáticamente (operaciones de liberación)

El objeto de la nueva aplicación solo ejecutará el destructor cuando se llame a la eliminación.

Si el programa sale sin ejecutar eliminar, provocará una pérdida de memoria

Suelte el puntero de clase al crear un objeto con nuevo:

	int* pTest = false;

Si el puntero de clase no ha sido inicializado por el objeto, no es necesario eliminarlo para liberarlo.


parte 2:

Estructura de datos y fundamentos de algoritmos (Wang Zhuo) (8): aplicación de tablas lineales

, debe crear una nueva tabla para devolver el resultado de la fusión de las dos tablas (la tabla fusionada final):


1.1:

Al principio, pensamos de manera muy simple, es decir, usar los parámetros reales para devolver la nueva tabla:

int Merge(Sqlist A, Sqlist B, Sqlist& C)
{
    Sqlist* C = new Sqlist;

    //验证我们开辟空间出来以后的C
    //是一个线性表还是一个指针
    Sqlist D;
    D = C;

    return true;
}

Pero en este momento, todavía hay un problema con el diseño de si C es una lista lineal o un puntero para verificar el espacio abierto:

Incluso si eliminamos la declaración aquí para abrir espacio

    Sqlist* C = new Sqlist;

Todavía no afecta el resultado de la última ejecución del programa (éxito)


1.2:

Cancele la tabla lineal de parámetros formales C y verifique si la C que creamos por separado es un puntero o una tabla lineal:

int Merge(Sqlist A, Sqlist B)//, Sqlist& C)
{
    Sqlist* C = new Sqlist;

    Sqlist D;
    D = C;
}

resultado:

 Sin duda, esto muestra que la C de nuestra nueva es un puntero, que todavía se ajusta a la especificación de formato básico de la declaración nueva que presentamos anteriormente.

Por lo tanto, si desea que el programa se ejecute correctamente (corrija este error), solo necesita cambiar la declaración de asignación a:

    D = *C;

Puede funcionar correctamente; tenga en cuenta (recuerde):

El símbolo agregado delante de C aquí debe ser "*", no "&"

Habitualmente siempre añadimos "&" delante de la dirección, porque olvidamos:

& es la dirección del operador

* es el operador de valor


2:

También podemos configurar directamente para devolver la tabla fusionada: (de esta manera no necesitamos establecer un parámetro real para devolver la nueva tabla)

Sqlist Merge(Sqlist A, Sqlist B)
{
    Sqlist* C = new Sqlist;
    return *C;
}

3:

Hemos estado escribiendo declaraciones de función para abrir espacio por nosotros mismos antes, pero aquí de repente descubrimos:

Hemos escrito la función InitList() inicializada antes, así que simplemente escriba la función de inicialización directamente:

int Merge(Sqlist A, Sqlist B, Sqlist& C)
{
    InitList(C);
    return true;
}


Por supuesto, también podemos escribir a mano la declaración de inicialización de acuerdo con (consulte) la definición de la función de inicialización que escribimos anteriormente:

4.1:

El método de escritura del valor de paso del puntero en la función InitList original: (valor de paso del puntero)

int Merge(Sqlist A, Sqlist B, Sqlist *C)
{
    C.elem = (Poly*)malloc(MAXlength * sizeof(Poly*));
    if (!C.elem)
        exit(OVERFLOW);
    C.length = 0;
    return OK;
}

4.2:

La forma de escribir por referencia en la función InitList original: (por referencia)

int Merge(Sqlist A, Sqlist B, Sqlist& C)
{
    C.elem = new Poly[100]; //在堆区开辟动态内存
    if (!C.elem)//分配失败        
        exit(OVERFLOW);
    C.length = 0;
    return OK;
}

Para obtener una explicación detallada y un análisis de cada paso de la inicialización de la tabla lineal, consulte:

Estructura de datos y fundamentos de algoritmos (Wang Zhuo) (2): Inicialización de la tabla lineal_宇-Blog de Yu-Blog de CSDN (Fin)


parte 3:

nuevo:

Para obtener más información, consulte: C Language Diary 26 Pointers and Functions, Dynamic Storage Allocation_宇-Yu's Blog-CSDN Blog

El ejemplo 6-10 asigna espacio para almacenar un arreglo bidimensional.

Programa fuente:

#include <iostream>
using namespace std;
int main()
{
	int i, j;
	int** p;
	p = new int* [4];
	//开始分配4行8列的二维数据
	for (i = 0; i < 4; i++)p[i] = new int[8];
	for (i = 0; i < 4; i++)	//给二维数组放入数据
	{
		for (j = 0; j < 8; j++)p[i][j] = j * i;
	}
	//打印数据
	for (i = 0; i < 4; i++)
		for (j = 0; j < 8; j++)
		{
			if (j == 0) cout << endl;
			cout << p[i][j] << "\t";
		}
	for (i = 0; i < 4; i++)
		delete[] p[i];
	delete[] p;
	return 0;
}//1

resultado:

  aquí

    p = nuevo int* [4];

Lo que quería expresar debería ser el llamado

    int(*p)[8];

Este significado, pero las reglas y especificaciones para abrir el espacio de puntero de segundo nivel (dimensional) no están claramente establecidas en el libro, como por ejemplo:

    p = nuevo int(*p) [4];

no trabajo:

Entonces, ¿cuáles son las reglas y especificaciones para usar el espacio de puntero secundario (dimensional) de este tipo de puntero multidimensional? !

Cuando se define una variable de matriz multidimensional o un objeto de matriz mediante el operador new, genera un puntero al primer elemento de la matriz.

El tipo devuelto contiene todas las dimensiones excepto la más a la izquierda. Por ejemplo:  

int* p1 = nuevo int[10];

Abra una matriz unidimensional y devuelva una dirección (es decir, un puntero) que apunte al espacio de almacenamiento de tipo int (int*)

int(*p2)[10] = nuevo int[2][10];

Abra una matriz bidimensional (elimine la unidimensional más a la izquierda [2], dejando int [10], entonces)

Lo que se devuelve es una dirección (es decir, un puntero) que apunta a un espacio de almacenamiento de matriz unidimensional como int[10] (int (*)[10]) 


A continuación, extendemos (extender) a tres dimensiones:

int(*p3)[2][10] = nuevo int[5][2][10];

Abra una matriz tridimensional (elimine el [5] unidimensional más a la izquierda, dejando int [2] [10], entonces) lo que se devuelve es un espacio de almacenamiento de matriz bidimensional que apunta a int [2] [10] dirección (es decir, puntero) (int (*)[2][10]) 

El formato general para crear dinámicamente una matriz bidimensional con new en C++ es:

TIPO (*p)[N] = nuevo TIPO [][N];

TIPO: tipo, N: el número de columnas de la matriz bidimensional.

Con este formato, se debe especificar el número de columnas, pero no es necesario especificar el número de filas. Aquí, el tipo de p es TYPE*[N], que es un puntero a una matriz con N columnas de elementos.


Hay otra forma de no especificar el número de columnas en la matriz: (este es el método que usamos aquí en este ejemplo)
 

    int** p; 
    p = new int*[10];  
    //Tenga en cuenta que int*[10] representa una matriz de punteros con 10 elementos
    para (int i = 1; i <= 10; i++)p[i] = new int[5];

{

Matriz de punteros:

Una matriz cuyos elementos son punteros es, en esencia, una matriz. (Por ejemplo, int *p[3] define tres punteros p[0], p[1], p[2])

}

Aquí, el nombre del puntero p del puntero secundario **p es de tipo "int **" (es decir, es un espacio de almacenamiento de matriz unidimensional que apunta a int[10] (como: int (*)[10 ]) dirección (es decir, puntero))

Específicamente asignado al puntero secundario **p puntero nombre p (uno que apunta a int[10]) matriz unidimensional (una (10 elementos) matriz de puntero) tipo dirección de espacio de almacenamiento (es decir, puntero)).

Fácilmente podemos notar que:

La "**p" aquí y nuestro diario en lenguaje C 25 (2) Suplemento: explicación detallada del proceso específico de matriz bidimensional y comprensión de puntero_宇-Blog de Yu-Blog CSDN (Interior: A[3][3] , int **p=A; al ejecutar p++, el compilador no puede usarlo porque no puede saber la longitud (ancho de columna: cuántas columnas hay en una fila) El "(*p)[5]" mencionado en " ( *p)[5]" y sus nombres de puntero representan un claro significado diferente:

El nombre de matriz p en (*p)[5] en realidad representa una dirección de fila

Es completamente diferente de aquí: p también representa la primera dirección (elemento) de la memoria del primer elemento (elemento) de la matriz bidimensional completa (fila 0 de la matriz bidimensional completa );

Por supuesto, muy similar a aquí, representa una matriz unidimensional, "[5]" significa que la matriz unidimensional contiene 5 elementos

Y aquí, al abrir el espacio de almacenamiento, el nombre de la matriz p en **p representa la dirección de un espacio de almacenamiento de matriz unidimensional


Además, el programa aquí (sí) no se puede cambiar a

    int(*p)[8];

forma:

#include <iostream>
using namespace std;
int main()
{
	int(*p)[8];
	int i, j;
	p = new int* [4];
	//开始分配4行8列的二维数据
	for (i = 0; i < 4; i++)p[i] = new int[8];
	for (i = 0; i < 4; i++)	//给二维数组放入数据
		for (j = 0; j < 8; j++)p[i][j] = j * i;
	//打印数据
	for (i = 0; i < 4; i++)
		for (j = 0; j < 8; j++)
		{
			if (j == 0) cout << endl;
			cout << p[i][j] << "\t";
		}
	for (i = 0; i < 4; i++)
		delete[] p[i];
	delete[] p;
	return 0;
}//1

resultado:

 ¿Por qué?

De hecho, la razón es muy simple:

Porque la p que usamos aquí es una matriz de punteros, no un puntero de matriz;

{

Puntero de matriz:

Un puntero a una dirección de matriz es esencialmente un puntero;

Matriz de punteros:

Una matriz cuyos elementos son punteros es, en esencia, una matriz. (Por ejemplo, int *p[3] define tres punteros p[0], p[1], p[2])

}


No sé lo que está haciendo. Siento que estos dos programas son exactamente iguales. Como resultado, el siguiente programa está lleno de errores después de ser ingresado:

#include <iostream>
using namespace std;
int main()
{
	int i,j;
	p = new int* [4];
	int** p;
	//开始分配4行8列的二维数据
	for (i = 0; i < 4; i++)p[i] = new int[8];
	for (i = 0; i < 4; i++)	//给二维数组放入数据
	{
		for (j = 0; j < 8; j++)p[i][j] = j * i;
	}
	//打印数据
	for (i = 0; i < 4; i++)
		for (j = 0; j < 8; j++)
		{
			if (j == 0) cout << endl;
			cout << p[i][j] << "\t";
		}
	//开始释放申请的堆
for (i = 0; i < 4; i++)
	delete[] p[i];
delete[] p;
return 0;
}

¿Alguien puede averiguar qué está pasando? ? ?

La parte del paréntesis de la función main() se escribe en el método de entrada chino.

adormecer

Supongo que te gusta

Origin blog.csdn.net/Zz_zzzzzzz__/article/details/128589494
Recomendado
Clasificación