2014-01-16 79 views
6

我在論壇上看了很多關於指針的帖子,Assigned函數,Free函數,FreeAndNil函數等等...我已經知道了自由函數不會刪除指向指定對象的指針引用並且FreeAndNil是不是......所有文章I閱讀對待這個主題考慮Create方法已經執行,或換句話說,考慮一個已經創建的對象。爲什麼Assigned對未初始化的變量返回true?

我的問題是:爲什麼Assigned函數對未初始化的對象變量返回true?

的榜樣:

procedure TForm1.FormCreate(Sender: TObject); 
var 
    Qry: TADOQuery;  
begin 
    if Assigned(Qry) then 
    ShowMessage('Assigned') 
    else 
    ShowMessage('Unassigned'); 

    Qry := TADOQuery.Create(nil); 

    if Assigned(Qry) then 
    ShowMessage('Assigned') 
    else 
    ShowMessage('Unassigned'); 
end; 

這個例子顯示 '分配' 的兩倍!

結論:緊隨Qry已被聲明並且在其創建方法執行之前,指向Qry的指針不是NIL

如果我把Qry := nil;放在第一行到上面的程序中,一切正常......它顯示'Unassigned'和'Assigned'。

爲什麼?

是否有任何安全的方法來知道一個類變量是否已經執行了它的create方法?

+4

看看這個:http://stackoverflow.com/questions/132725/are-delphi-variables-initialized-with-a-value-by-default – idursun

+1

「類變量已經執行了它的create方法「變量沒有任何方法! 'var o:TObject;我:整數; s:絃樂;我:= TStringList.Create.Count; s:= TStringList.UnitName; o:= TStringList.Create;' - 這三個語句中的每一個都有相同的結構:有一些任何表達式,它計算一些任何值;並且存在值(但不是表達式,該點不再存在)的變量被保存到。當表達式被執行時(用這些「方法」)還沒有var。當有變化 - 沒有更多的表達 –

回答

3

因爲當創建一個指針時,它帶有任何垃圾值在該內存位置。如果你想寫NIL,它需要一些CPU週期,我認爲它不是由Delphi自動完成的,因爲你可能想要更快的東西。在你的例子中,爲什麼把NIL分配給一個變量,如果不久之後你會把另一個值放進去呢?

+2

我不知道爲什麼你被拒絕了(兩次)。 –

+0

看起來像一些人在答案中的問題有問題嗎? (即使rethorical問題...) – Rodrigo

7

您的變量是局部變量,因此未初始化。它可以包含任何值。

documentation說:

Win32平臺的 內容的局部變量是不確定的,直到一個值分配給 他們。

請注意,作爲實現細節,某些類型被管理,甚至託管類型的局部變量也被初始化。託管類型的示例包括:字符串,接口,動態數組,匿名類型和變體。

你問:

有沒有知道,如果一個類變量已經擁有了創建方法執行任何安全的方式?

如果該變量是局部變量,則答案爲否。程序員對你負有責任。在實踐中,它很少是一個問題,因爲良好的代碼具有簡短的程序,這使得你很難滑落。即使你這樣做,編譯器也會一直提醒你。

其他類型的變量,如類字段和全局變量被初始化。

+0

我認爲德爾福/ LLVM初始化類指針,因爲它們就像那裏的接口指針。我想知道是否有很多「錯誤」報告,例如「我的應用在iPad上工作正常,但變量在iOS模擬器上失敗無測試」;-) –

4

Assigned函數(重點煤礦)的文檔:

使用分配給確定被P所引用的指針或過程是否是零。 P必須是指針或過程類型的變量引用。 指定的(P)對應於針對指針變量的測試P <> nil,對於程序變量,測試P <>零。

如果P爲零,則分配返回false,否則返回true。

注意:Assigned不能檢測懸掛指針 - 即,不是零但不再指向有效數據的指針。例如,在分配的代碼示例中,分配不會檢測到P無效的事實。

Assigned功能得到有效實施爲:

function Assigned(const P): Boolean; 
begin 
    Result := Pointer(P) <> nil; 
end; 

因此函數是不是真的檢查值是否真的被分配。而是檢查分配的副作用。

  • 其結果的功能是保證返回True如果分配
  • 但是,如果值爲未初始化,則行爲未定義。基本上,由於未初始化的值具有先前操作遺留的垃圾值,因此可能是,或者如果可能不是

要注意的另一件事是Assigned無法確定其值的有效性。例如。即使底層對象不再有效,以下呼叫Assigned也會返回True

var 
    LObject: TObject; 
begin 
    LObject := TObject.Create; 
    LObject.Free; 
    if Assigned(LObject) then ShowMessage('Still assigned!?'); 
end; 

編輯:附錄

在回答你問題的第二部分。

是否有任何安全的方法知道一個類變量是否已經執行了它的create方法?

沒有安全的方法來確定是否創建了一個對象實例。 (也沒有辦法可靠地確認它還沒有被銷燬。)

但是,有一些約定(和良好的做法),你可以按照以幫助你的方式。

首先請注意,如果創建了某些代碼的故意功能,則應該只是「不確定」。例如。如果你打算讓一個對象「懶惰初始化」。

  • 我想在這裏說的是:決不檢查Assigned僅僅是因爲你擔心,有可能是防止它被分配了一個錯誤。
  • 這不僅是不可能做到可靠,但你過分複雜的代碼...其中增加錯誤的機會。
  • 此外,如果您發現意外未分配的東西,那麼您可以對此做些什麼?忽略它會簡直毫無意義。另外,沒有什麼好說的:「好吧,然後我會創建對象」。因爲這樣你就可以在多個地方複製創建邏輯。
  • 基本上你應該儘量讓你的程序的每個部分都正確 - 你的程序不要試圖在任何地方進行仔細檢查。

所以,現在,我們(希望)同意,如果事情是創建如果你刻意選擇了爲創建是可選的,你只檢查。你這樣做如下:

  • 在第一次機會,確保變量/場參考被初始化。因此,它被保證被分配一個值,這意味着該對象不被創建。 (是的,命名有點扭曲
  • 您可以將可放大/字段引用設置爲對象的新實例,或者通過複製已存在對象的另一個引用來設置它。 (注現有refernce也可能是,但這並不會引起任何問題。
  • 如果你破壞對象(甚至只是想停止使用從基準),設置您的變量/現場參考再次。
  • 注意:Delphi已經初始化一個新類的成員字段。所以這些不需要特別的關注。
相關問題