2014-11-25 49 views
0

僅出於好奇和教育和澄清的原因我想問一下,我使用參考和值的方式是好的或不好的。帶參考文獻的最佳做法

理論上:

class ComplexGraphicalShape { 
... 
public: 
    void setRasterImageURL(const QString &rasterImageURL); 
    const QString &rasterImageURL() const; 
... 
private: 
    const QString *_rasterImageURL; 
}; 

... 

void ShadowGram::setRasterImageURL(const QString &rasterImageURL) { 
    safeDelete(_rasterImageURL); // handle deletion 
    _rasterImageURL = new QString(rasterImageURL); 
} 

const QString &ShadowGram::rasterImageURL() const{ 
    // Question 2: Why is it a problem if I return 
       // return "www.url.com/shape_url.jpg" 
    return *_rasterImageURL; // that is the right way 
} 

... 

complexGraphicalShape().setRasterImageURL(kURLImagesToShare + imageName); 
complexGraphicalShape().setRasterImageURL("www.url.com/url.jpg"); // Question 1. 

我的第一個問題是,我如何能長久使用的是內部setRasterImageURL functioncall創建的臨時對象的引用?這個變量在什麼地方存在?(在堆棧中如果我沒有弄錯,但是如果我用另一個臨時參考調用另一個函數會怎麼樣

我的第二個問題是,爲什麼我在問題2一節中收到警告?用這個return "www.url.com/shape_url.jpg"那個東西是一種類似於多久我可以使用臨時對象

感謝您的時間的回答和解釋

+0

你爲什麼用'new'創建'QString'? – 2014-11-25 10:41:01

+0

我認爲「參考的有效期是多久?」問題在主題 – 2014-11-25 12:50:41

回答

3

Q1:只要臨時串存在作爲臨時引用,是「綁定」的,也就是說 - 只要你在「內部」函數中,這當然包括了在這個函數中被稱爲「內部」的所有函數。存儲另一參考此臨時字符串確實不存在延長臨時對象的生命週期。

complexGraphicalShape().setRasterImageURL("www.url.com/url.jpg"); 
// the temporary object is "destroyed" when it goes out of scope, and it's scope is just the called function 

Q2:與返回的問題是,使用「C字符串」(字符數組)來創建臨時QString對象(上堆,仍然在函數內部),並返回參照該暫時的。由於此臨時對象在此函數返回後立即被銷燬,因此您的引用永遠無效並引用一個死對象。另一方面 - 返回對成員變量的引用有效,因爲這個對象沒有被銷燬,所以只要你的主要對象存在,引用就是有效的。

const QString &ShadowGram::rasterImageURL() const{ 
    return "www.url.com/shape_url.jpg" 
    // the temporary object is destroyed here, before the function returns, reference is invalid 
} 
+1

第一個臨時表的生命週期不受綁定到它的引用的影響,它將一直保留到完整表達式的末尾,即函數返回並且引用已消失。另外,'QString'不是'std :: string' – 2014-11-25 10:45:41

+0

非常感謝Freddie的解釋! – flatronka 2014-11-25 11:41:09

3
  1. 暫時存在,直到setRasterImageURL的回報,這樣你就可以安全地傳遞下去對它的引用,但你必須要小心,不要保存以供日後參考。臨時文件存儲在編譯器想要的任何地方。該引用很可能通過寄存器或堆棧傳遞。

  2. 這是一個問題,因爲您要返回對臨時QString對象的引用,並且該對象在函數返回時被銷燬。根本不允許使用該參考。

經過參考「向內」的功能(通常)安全的,只要你不存儲,同時從函數傳遞引用「向外」需要你確保引用的對象函數返回時仍然存在。

+0

好的「規則」,謝謝你! – flatronka 2014-11-25 11:41:40

3

我的第一個問題是,我如何能長久使用的是內部setRasterImageURL functioncall創建的臨時對象的引用?

它不是函數調用中創建的,它的調用者的堆棧上創建之前的函數被調用,並在函數返回之後被破壞。

如果我叫與臨時參考另一個功能位置存在變量?(堆棧如果我沒有記錯的話,但什麼。

是,在堆棧上,它在被破壞;函數調用返回時(在「充分體現」結束)之後。

那個東西是一種類似於多久我可以使用臨時對象?

直到創建臨時表達式的完整表達式的末尾,即return語句,因此它在函數甚至完成返回之前立即超出範圍。這就是爲什麼你會得到一個警告 - 返回的引用綁定到一個不再存在的對象,並且永遠不會安全使用。綁定到一個函數調用(5.2.2)的參考參數的臨時對象,持續直到完成 -

這兩種情況下,由12.2 [class.temporary]在標準的第5段所覆蓋包含調用的完整表達式。
- 在函數return語句(6.6.3)中臨時綁定到返回值的生命週期不會被擴展;在return語句的完整表達式的末尾臨時被銷燬。

+1

這對應於創建對臨時對象的const引用的情況,當此臨時對象的存在時間與引用一樣長時,並且在表達式結尾處不會被銷燬?例如'const int&a = {}; if(a == 5)do_sth(a); int another_variable = a;'?顯然臨時(由{}'創建的)在表達式的末尾不會被銷燬......這是不同的規則嗎? – 2014-11-25 10:58:25

+0

@FreddieChopin返回的引用不是臨時對象。 – molbdnilo 2014-11-25 11:16:30

+0

@molbdnilo - 你誤解了我的評論。我指的是在表達結束時臨時銷燬的信息。 – 2014-11-25 11:18:01