Tengo una matriz a la que quiero poder compartir el acceso a través de una matriz de estructura que contiene referencias a dicha matriz.

¿Hay alguna forma de lograr esto para que pueda modificar la matriz extrayendo de este búfer?

struct something {
    vector<vector<double>> &a;
};

something buffer[3];

void modify(something &arr) {
    (arr.a)[0][0] = 10;
    cout << (arr.a)[0][0] << endl;
}

int main(int argc, const char * argv[]) {
    vector<vector<double>> a(5, vector<double>(5));
    buffer[0] = {a};
    modify(buffer[0]);
    // want this to print 10
    cout << a[0][0] << endl;
    return 0; 
}

El problema con esto, por supuesto, es que una estructura con una referencia dentro no tiene un constructor predeterminado y, por lo tanto, no se puede inicializar de esta manera.

c++
0
foerever 29 abr. 2020 a las 16:21

3 respuestas

La mejor respuesta

Este es un buen caso de uso para los punteros, ya que pueden construirse por defecto y puede asignarles diferentes variables, a diferencia de las referencias:

struct something {
    vector<vector<double>> *a = nullptr; //pointer variable
};

something buffer[3];

void modify(something &arr) {
    //include nullptr check to prevent segmentation error
    if(!arr.a) return;
    //dereference arr.a to access it
    (*(arr.a))[0][0] = 10; 
    cout << (*(arr.a))[0][0] << endl; //dereference arr.a to access it
}

int main(int argc, const char * argv[]) {
    vector<vector<double>> a(5, vector<double>(5));
    buffer[0] = {&a};
    modify(buffer[0]);
    // want this to print 10
    cout << a[0][0] << endl;
    return 0; 
}

Tenga cuidado de rastrear la vida útil de los objetos señalados por los punteros, ya que si se salen del alcance antes que los punteros, los punteros se colgarán.

1
Azam Bham 29 abr. 2020 a las 13:36

Primero debe crear las matrices para poder consultarlas. De esa manera puede inicializar las referencias correctamente:

vector<vector<double>> matrices[3];
something buffer[]{matrices[0], matrices[1], matrices[2]};

Sin embargo, ese no es el único problema. Otra es que intentas asignar something:

buffer[0] = {a};

Esto no está permitido porque something no es asignable. No es asignable porque la clase contiene un miembro de referencia.

// want this to print 10

No hay forma de hacer que la referencia global se refiera a una variable local.

Dado que está tratando de usar la clase de varias maneras que son contradictorias para tener un miembro de referencia, quizás sería mejor rediseñarla para no usar una referencia.

Esto parece un caso de uso potencialmente bueno para un puntero. A diferencia de las referencias, se pueden asignar punteros después de la inicialización. Sin embargo, tenga mucho cuidado al almacenar punteros en objetos locales en la matriz global. Es muy fácil terminar con un puntero no válido.

1
eerorika 29 abr. 2020 a las 13:40

Es mejor pensar que una referencia no es un objeto real, sino una abstracción para "una forma de acceder al objeto". Como no son datos concretos, no se pueden poner en contenedores. Su mejor apuesta para lograr un efecto similar es crear una serie de punteros. Dependiendo de su estándar C ++ y las necesidades de asignación de memoria, deberá elegir entre punteros inteligentes sin formato o C ++ 11 (del encabezado <memory>).

1
Joald 29 abr. 2020 a las 13:35