2012-09-27 64 views
3

最近,我在iOS上經歷了幾年的獨家Objective-C之後,我一直在追趕我的C++,並且在'new style'C++中出現的主題是RAII可以將延遲加載視爲RAII的一個示例嗎?

爲了確保我理解RAII概念正確地說,你會考慮Objective-C懶加載屬性訪問器是一種RAII類型嗎?例如,檢查以下訪問方法

- (NSArray *)items { 
    if(_items==nil) { 
     _items=[[NSArray alloc] initWithCapacity:10]; 
    } 
    return _items 
} 

這會被視爲RAII的一個例子嗎?如果不是,你能解釋我錯在哪裏嗎?

+0

爲什麼你認爲懶加載是RAII的一個元素? – tenfour

+0

我在猜測,因爲我顯然不太理解RAII :) – codemonkey

+1

這是一個完全合法的問題,我只是想讓這個問題對大家有所幫助,包括理性思考。問題是這樣的:「柚子是氣候變化的一個元素嗎?」這將有助於解釋你認爲的連接是什麼。 – tenfour

回答

4

RAII不幸被廣泛濫用。

最初的概念資源獲取是初始化是關於使用構造函數來保證發生的事情。在這樣的觀念:

std::fstream out("somefile.txt", "w"); 

應該保證的是,如果曾經創建out,則該文件存在,並且隨時可以使用。

因此,延遲加載與RAII相反!

注意:現在,雖然RAII主要用於指代自動清理。一個例子是智能指針。這有點遠離它的最初目標。


關於清理,另一個成語是作用域綁定資源管理 SBRM。儘管如此,它並沒有完全捕獲確定性清理的想法。 SBRM的想法是,當某個對象超出範圍時,可以保證清理資源。例如,這可以通過boost::scoped_ptr來實現。

但是,這無法捕獲unique_ptr做什麼,因爲您實際上可以return a unique_ptr因此讓資源逃脫它創建的範圍!

+1

*懶加載是RAII的相反!*這是不正確的。對於調用者來說,RAII對象可以整天延遲加載,調用者不需要知道。在你的例子中,我不認爲RAI​​I意味着該文件是立即創建的。它只意味着對象不會在沒有*概念*創建和初始化的情況下存在。所以它基本上禁止像'Init'或'Load'或'Create'這樣的方法。換句話說,說他們是對立的,給他們一種不存在的關係。有些情況下他們會發生衝突,但總的來說,他們只是無關的概念。 – tenfour

+0

@tenfour:我同意延遲加載可能會使用戶透明,但是如果延遲加載失敗,您將如何處理它?用戶肯定有資源,但你沒有獲得它!舉一個明顯的例子,想一下互斥鎖。通過RAII,構建鎖對象可以確保我鎖定了互斥鎖,因此我可以安全地繼續前進並完成我的任務。現在假設你決定延遲加載,我獲得了互斥鎖,做了一些不可撤銷的事情,並使用觸發延遲加載的「鎖定」項併產生異常。 Oups? –

+0

這可能取決於你如何寬泛地應用術語「資源」。但是如果構造函數不實際獲取打開的文件描述符,那麼就像Matthieu所說,資源獲取*不是初始化,資源獲取是後來可能發生的任何事情(因此任何後來的任何事情都可能由於失敗而失敗資源獲取)。可以描述什麼叫「概念創建文件」,「建立一個簡單的類不變式」(可能:它知道它指的是什麼文件名)。它可能會獲得* a *資源(例如複製名稱),但不會獲得*資源。 –

0

否; RAII是將具有動態存儲的某個對象包裝在具有自動存儲的對象中,並且在具有自動存儲的對象被銷燬時被銷燬。

延遲加載(只有當你真的需要它,而不是之前加載一個對象)和RAII沒有真正相關。

2

不,完全沒有。此外,「新風格的C++」的意思是「至少在過去的十五年裏,每個人都一直在這樣做」。

RAII涉及自動存儲持續時間清理它們所擁有的析構函數中的動態對象的對象。所有權的確切時間是無關緊要的。

+1

我想我比我想的更過時:) – codemonkey

3

縮寫名稱初始化時,成語的重點是破壞。 資源獲取是初始化更多關於作用域綁定資源管理,即讓對象管理資源並在超出範圍時將其清除。