2009-09-08 13 views
5

Quiero crear un grupo de registros (RWell) y almacenarlos en una matriz en un cierto orden. Entonces quiero crear una nueva matriz (diseño diferente) y reacomodar los registros en ella. Por supuesto, no quiero duplicar datos en la RAM, así que pensé que en la segunda matriz debería poner punteros a los registros en la primera matriz. Sin embargo, no puedo hacer eso. ¿Alguien puede decir lo que está mal con el código de abajo? Gracias Matriz de (punteros a un registro)

Type 
    RWell= record         
    x: string; 
    i: integer; 
    end; 

    PWell= ^RWell; 

    RWellArray= Array[0..12, 0..8] of RWell;  


procedure TClass1.CreateWells 
var 
    WellMX: RWellArray; 
begin 
    { should I initialize the WellXM here? } 
    { note: WellXM is a static array! } 

    other stuff 
end; 



var Wells: array of PWell; 
procedure TClass2.AddWell(aWell: RWell); 
begin 
aWell.Stuff:= stuff; {aWell cannot be readonly because I need to change it here} 

SetLength(Wells, Length(Wells)+ 1); { reserve memory } 
Wells[High(Wells)]:= @aWell; 
end; 



procedure TClass3.DisplayWell; 
var CurWell: RWell; 
begin 
CurWell:= CurPrimer.Wells[iCurWell]^;  <--- AV here (but in debugger the address is correct) 
end; 

resueltos por Rob K.

+1

Obtendrá comentarios sobre su técnica para agregar al final de la matriz dinámica. Puede ser ineficiente y puede fragmentar la memoria. Sería mejor que hicieras la matriz del tamaño que necesitarás solo una vez, y luego asignar valores al siguiente elemento no asignado a medida que avanzas. Otra opción es usar un 'TList', que es muy bueno para almacenar punteros. A partir de Delphi 2009, incluso podría ser seguro como 'TList '. –

+0

No sé el tamaño de esa matriz en tiempo de ejecución. Y sé que no es óptimo establecer su longitud. Pero es muy pequeño (menos de 600 entradas) por lo que la fragmentación será menor. No me molestaré en cambiarlo ahora. Gracias por la sugerencia :) – Ampere

+0

Estoy de acuerdo en que es mejor usar una lista aquí. –

Respuesta

6

En su función AddWell, que están pasando por el registro valor. Eso significa que la función obtiene una copia del parámetro real. Está almacenando un puntero al parámetro formal, que probablemente sea solo una ubicación en la pila local de la función.

Si quieres un puntero a un pozo, a continuación, pasar un puntero a un pozo:

procedure AddWell(AWell: PWell); 
begin 
    SetLength(Wells, Length(Wells) + 1); 
    Wells[High(Wells)] := AWell; 
end; 

Otra opción es pasar por el registro valor const. Para los registros, esto significa que el parámetro real se pasa como referencia. Un puntero al parámetro formal es también un puntero al parámetro real:

procedure AddWell(const AWell: RWell); 
begin 
    SetLength(Wells, Length(Wells) + 1); 
    Wells[High(Wells)] := @AWell; 
end; 

yo no realmente confiar en eso, sin embargo. Cuando desee punteros, pase punteros. Algunas personas intentan evitar punteros en su código, pero no tienen nada de qué temer.

+1

No está garantizado que AFAIK const pase por referencia, por lo que no confiaría en él aquí. –

+0

Primero no funcionó: tipos incompatibles PWell y RWell. El segundo trabajo PERO dentro de ese procedimiento tengo un código que necesita modificar AWell, que ahora es de solo lectura (const). (lo siento, no proporcioné el código completo para que mi pregunta sea fácil de leer/entender). – Ampere

+0

La primera no funcionó porque no cambiaste la * persona que llama *. Debe pasar un puntero cuando llame a la función: 'AddWell (@WellMX [2, 3])'. –

Cuestiones relacionadas