2015-05-04 96 views
-2

我有兩個代碼段,我希望同樣的結果:C++採取臨時對象的地址

第一招:

SomeClass somefunc(...){ 
    SomeClass newObj; 
    //some codes modify this object 
    return newObj; 
} 

int main(){ 
    SomeClass *p; 
    p = &(somefuc(...)); 
} 

第二個:

SomeClass *somefunc(...){ 
    SomeClass newObj; 
    //some codes modify this object 
    return &newObj; 
} 

int main(){ 
    SomeClass *p; 
    p = somefunc(...); 
} 

爲什麼當我嘗試構建第一個代碼段時,第二個代碼段沒有產生錯誤時,我得到了「獲取臨時對象的地址」錯誤?

+0

請顯示您的實際代碼。 – tenfour

+3

片段無法編譯。第二個是因爲你試圖從聲明爲返回SomeClass的函數返回'SomeClass *'。還要注意'newObj'不是一個臨時的 - 它是一個命名變量。取其地址是沒有問題的 - 問題在於在變量的生命週期結束後使用所述地址。 –

+0

第二個例子甚至不應該編譯,而且'p =&(somefuc(...));'不應該編譯,因爲你不能得到一個右值的地址 – vsoftco

回答

0

第一個代碼段確實沒有編譯,因爲正如編譯器所說的那樣,您不能獲取臨時對象的地址,因爲它將在表達式末尾(此處爲賦值)被銷燬。因此,保存地址是沒有意義的。

第二個代碼段確實編譯,,但仍然不正確,儘管看起來由於here(至少如果您嘗試通過指針訪問對象)的原因工作。

2

在你思考這個之前,你需要學習臨時生命的規則。

大範圍的情況是臨時對象在創建它的全表達式的末尾被銷燬。言下之意是,如果

SomeClass *p; 
p = &(somefunc(...)); 

被允許工作,p將是一個懸擺指針,目標不再存在的對象。

上述規則的一個很大的例外是,當具有自動生命期的引用是直接綁定到臨時對象時,臨時的生命週期擴展爲等於引用的生命週期。請注意,這不包括const T& make_lvalue(const T& t) { return t; },因爲引用不是直接綁定的,也不是類成員引用。

有幾種情況是完全安全的,其中臨時地址只能立即使用,不能在以後存儲。例如

memcpy(buffer, &f(), sizeof(decltype(f()))); 

當然,這導致你遇到錯誤「臨時地址」,但你可以通過

memcpy(buffer, std::addressof(f()), sizeof(decltype(f()))); 

解決它,但不存儲所產生的指針。

0

第一個示例不會編譯,因爲somefunc會返回一個值,並且您嘗試獲取它返回的臨時事件的地址。這會工作:

Someclass* p; 
Someclass val = somefunc (...); 
p = &val; 

第二個例子不能編譯 - 或不應該 - 因爲somefunc應該返回一個SomeClass的,而是它返回一個指向SomeClass的。讓它返回Someclass *,然後它應該被編譯 - 但是現在你要返回一個指向局部變量的指針,這個變量在你離開函數後不再存在。最佳解決方案是第一個例子,在這裏進行了修補。

+0

第二個例子...「應該工作」什麼?它返回一個懸掛指針,絕對沒用。你最好返回'void'。 –

+0

啊,是的。我編輯了我的答案來說這個。 –