c++ - sirven - punteros y matrices en c
¿Para qué sirve la indirección múltiple en C++? (8)
¿Bajo qué circunstancias podría desear usar direccionamiento indirecto múltiple (es decir, una cadena de punteros como en Foo **
) en C ++?
Carl: Tu ejemplo debería ser:
*p = x;
(Tienes dos estrellas) :-)
El uso más común como @aku señaló es permitir que un cambio en un parámetro de puntero sea visible después de que la función regrese.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
Esto se imprimirá
12
Pero hay varios otros usos útiles, como en el siguiente ejemplo, para iterar una matriz de cadenas e imprimirlas en el resultado estándar.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
El uso más común de IMO es pasar referencia a variable de puntero
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
Puede crear una matriz dentada multidimensional utilizando dos punteros:
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
En C, la expresión idiomática es absolutamente necesaria. Considere el problema en el que desea que una función agregue una cadena (C pura, por lo tanto, una char *) a una matriz de punteros a char *. El prototipo de función requiere tres niveles de direccionamiento indirecto:
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
Lo llamamos de la siguiente manera:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I''m adding");
En C ++ tenemos la opción de usar referencias en su lugar, lo que produciría una firma diferente. Pero aún necesitamos los dos niveles de direccionamiento indirecto que solicitó en su pregunta original:
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
Si pasa un puntero como parámetro de salida, es posible que desee pasarlo como Foo**
y establecer su valor como *ppFoo = pSomeOtherFoo
.
Y desde el departamento de algoritmos y estructuras de datos, puede usar ese doble direccionamiento indirecto para actualizar los punteros, que puede ser más rápido que, por ejemplo, intercambiando objetos reales.
Un ejemplo simple sería usar int** foo_mat
como una matriz 2d de enteros. O también puede usar punteros a punteros, digamos que tiene un puntero void* foo
y tiene 2 objetos diferentes que tienen una referencia con los siguientes miembros: void** foo_pointer1
y void** foo_pointer2
, al tener un puntero a un puntero, puedes verificar si *foo_pointer1 == NULL
que indica que foo es NULL. No podría verificar si foo es NULL si foo_pointer1 fuera un puntero regular. Espero que mi explicación no haya sido demasiado desordenada :)
Un escenario común es cuando necesita pasar un puntero nulo a una función y hacer que se inicialice dentro de esa función y se use fuera de la función. Sin indirección de multiplicidad, la función de llamada nunca tendría acceso al objeto inicializado.
Considere la siguiente función:
initialize(foo* my_foo)
{
my_foo = new Foo();
}
Cualquier función que llame ''initialize (foo *)'' no tendrá acceso a la instancia inicializada de Foo , ya que el puntero que se pasa a esta función es una copia. (El puntero es solo un entero después de todo, y los enteros se pasan por valor).
Sin embargo, si la función se definió así:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
... y se llamó así ...
Foo* my_foo;
initialize(&my_foo);
... entonces la persona que llama tendría acceso a la instancia inicializada, a través de ''mi_foo'', porque es la dirección del puntero que se pasó a ''inicializar''.
Por supuesto, en mi ejemplo simplificado, la función ''inicializar'' podría simplemente devolver la instancia recién creada a través de la palabra clave return, pero eso no siempre se adapta, tal vez la función necesite devolver algo más.
Por lo general, cuando pasa un puntero a una función como valor de retorno:
ErrorCode AllocateObject (void **object);
donde la función devuelve un código de error de éxito / falla y rellena el parámetro del objeto con un puntero al nuevo objeto:
*object = new Object;
Esto se usa mucho en la programación COM en Win32.
Esto es más una cosa de C que hacer, en C ++ a menudo puedes incluir este tipo de sistema en una clase para hacer que el código sea más legible.