2009-09-08 41 views
5

Tôi muốn tạo một nhóm bản ghi (RWell) và lưu trữ chúng trong một mảng theo một thứ tự nhất định. Sau đó, tôi muốn tạo một mảng mới (bố cục khác nhau) và sắp xếp lại các bản ghi trong đó. Tất nhiên, tôi không muốn sao chép dữ liệu trong RAM vì vậy tôi mặc dù trong mảng thứ hai tôi nên đặt con trỏ đến các bản ghi trong mảng đầu tiên. Tuy nhiên, tôi không thể làm điều đó. Bất kỳ ai cũng có thể cho biết có gì sai với mã bên dưới? Cảm ơnMảng (con trỏ tới bản ghi)

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; 

giải quyết bằng cách Rob K.

+1

Bạn sẽ nhận được nhận xét về kỹ thuật của bạn để gắn vào cuối mảng động. Nó có thể không hiệu quả và có thể phân mảnh bộ nhớ. Bạn nên làm cho mảng tốt hơn kích thước bạn sẽ cần chỉ một lần, và sau đó gán giá trị cho phần tử chưa được gán tiếp theo khi bạn đi. Một tùy chọn khác là sử dụng một 'TList', lưu trữ con trỏ rất tốt. Tính đến năm 2009 Delphi, nó thậm chí có thể được loại an toàn như 'TList '. –

+0

Tôi không biết kích thước của mảng đó khi chạy. Và tôi biết nó không phải là tối ưu ho tôi đặt chiều dài của nó. Nhưng nó rất nhỏ (dưới 600 mục) nên sự phân mảnh sẽ nhỏ. Tôi sẽ không bận tâm thay đổi nó ngay bây giờ. Cảm ơn bạn đã đề xuất :) – Ampere

+0

Tôi đồng ý rằng nên sử dụng danh sách ở đây tốt hơn. –

Trả lời

6

Trong chức năng AddWell của bạn, bạn đang đi qua kỷ lục bởi giá trị. Điều đó có nghĩa là hàm nhận được bản sao của thông số thực tế. Bạn đang lưu trữ một con trỏ đến tham số chính thức, có lẽ chỉ là một vị trí trên ngăn xếp cục bộ của hàm.

Nếu bạn muốn có một con trỏ đến một cái giếng, sau đó vượt qua một con trỏ đến một cái giếng:

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

lựa chọn khác là để vượt qua kỷ lục của giá trị const. Đối với các bản ghi, điều này có nghĩa là tham số thực tế được chuyển như một tham chiếu. Một con trỏ đến tham số chính thức cũng là một con trỏ đến tham số thực tế:

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

Tôi sẽ không thực sự dựa vào điều đó. Khi bạn muốn con trỏ, hãy chuyển con trỏ. Một số người cố gắng tránh các con trỏ trong mã của họ, nhưng họ không có gì phải sợ.

+1

AFAIK const không được đảm bảo để thực thi truyền qua tham chiếu, vì vậy tôi sẽ không dựa vào nó ở đây. –

+0

Đầu tiên không hoạt động: Các loại không tương thích PWell và RWell. Cách thứ hai làm việc NHƯNG bên trong thủ tục đó tôi có mã cần sửa đổi AWell, bây giờ là chỉ đọc (const). (xin lỗi, tôi đã không cung cấp mã đầy đủ để làm cho câu hỏi của tôi dễ đọc/dễ hiểu). – Ampere

+0

Người đầu tiên không làm việc vì bạn không thay đổi * người gọi *. Bạn cần truyền con trỏ khi bạn gọi hàm: 'AddWell (@WellMX [2, 3])'. –

Các vấn đề liên quan