2014-12-10 97 views
0

我需要調用一個爲我返回對象的函數。問題是對象有一個析構函數,它可能會在函數輸出被分配到另一個對象之前破壞數據。 在我的節目,我有這增加了兩個矩陣和返回兩個矩陣的和運營商+:我必須依賴編譯器NRVO嗎?

C=A+B 

根據的名稱返回值優化(NRVO),下面的代碼不應該調用析構函數權

Matrix operator+(const Matrix &m1, const Matrix &m2) 
{ 
    Matrix sum; 
    m1.clone(sum); 
    for... 
     for... 
      sum.members[i][j]+=m2.members[i][j]; 
    return sum; 
} 

我的問題是,我不相信信賴NRVO,因爲它取決於編譯器。如果我將代碼提供給其他人,他可能會編譯代碼,並且他的編譯器會給出不同的結果。

那麼,有什麼辦法強制編譯器給我什麼我需要什麼,或者我必須將我的代碼更改爲不受歡迎的形式如下?

Matrix sum(Matrix &result, const Matrix &m1, const Matrix &m2) 

編輯:

只是爲了更多地解釋,我認爲考慮NRVO的probram運行如下:

compiler reaches to C=A+B 
operator + is called 
object sum is created 
object sum is calculated as sum of m1 and m2 
sum is returned but its destructor is not called 
the value of sum is directed to variable C 
after function containing variable C reaches end, the destructor of C is called. 

當不施加NRVO雖然,我想到:

compiler reaches to C=A+B 
operator + is called 
object sum is created 
object sum is calculated as sum of m1 and m2 
sum is returned and its destructor is called which releases all data allocations 
the return value of the operator+ is already destroyed so an invalid data is associated to variable C 
... 
+1

(臨時創建的對象),如果你的類做你說什麼確實,你需要修復它。 – juanchopanza 2014-12-10 21:44:50

+0

您編寫的代碼不應依賴於特定的編譯器優化才能正常運行。 – 2014-12-10 21:45:40

+2

這聽起來像你需要閱讀關於對象的生命週期。請指出您希望析構函數調用的代碼中的位置,我們應該能夠清除它。 – Pradhan 2014-12-10 21:48:15

回答

3

問題是對象具有析構函數,可能會在函數輸出被分配到另一個對象之前破壞數據。

這不是問題。對象將被正確複製或通過優化消除不必要的副本。如果您的副本正確實施,最終結果將是相同的(當然,除非最優代碼不合適)。如果對象拷貝過於昂貴,那麼你可能應該在寫入語義上使用拷貝,而實際的矩陣對象將是堆上創建的真實對象的薄包裝。

當不施加NRVO會有什麼實際發生:

compiler reaches to C=A+B 
operator + is called 
object sum is created 
object sum is calculated as sum of m1 and m2 
temporary object of type Matrix created as a copy of object sum 
object sum destroyed 
temporary assigned to C 

,你可以看到最終的結果是一樣的,只是事倍功半