2011-08-15 58 views
1

下面的類旨在監視另一個進程的變化狀態;它的構造函數設置了const引用以方便訪問相關變量。這裏的構造函數代碼:爲什麼C++編譯器在此處生成臨時文件?

template<typename FZYRSRC> 
struct MergeableHeight: public FzyQty<FZYRSRC> 
{ 
MergeableHeight( 
    const DDBuffer& me, const DDBuffer& neighbor, Orientation ori, bool useV =false) 
: iP(me[PEAK_V].index()), iNP(neighbor[PEAK_V].index()), 
    facingNeighbor(iP < iNP ? RIGHT_V : LEFT_V), //vertex pointing to neighbor 
    facingMe(iP < iNP ? LEFT_V : RIGHT_V),  //neighbor's vertex pointing to me 
    iMyEdge(edgeBar(me,facingNeighbor)), iNeighborEdge(edgeBar(neighbor,facingMe)), 
    myEdgeVal(me[facingNeighbor].datum()), neighborEdgeVal(neighbor[facingMe].datum()), 
    myPeakVal(me[PEAK_V].datum()), useVolatility(useV),o(ori)    
{} 

//member functions etc. 
private: 
     virtual MergeableHeight* clone()const {return new MergeableHeight(*this);} 
const int &iP, &iNP; 
const PeakVertex facingNeighbor, facingMe; //PeakVertex is Enum {LEFT_V,PEAK_V,RIGHT_V} 
const int &iMyEdge, &iNeighborEdge; 
const double &myEdgeVal, &neighborEdgeVal, &myPeakVal; 
const Orientation o; 
bool useVolatility; 
    }; 

感興趣的類的數據成員是兩個const int的引用iMyEdge和iNeighborEdge,初始化爲

iMyEdge(edgeBar(me,facingNeighbor)), iNeighborEdge(edgeBar(neighbor,facingMe)), 

和3常量浮動引用myEdgeVal,neighborEdgeVal,myPeakVal,初始化as

myEdgeVal(me[facingNeighbor].datum()), 
    neighborEdgeVal(neighbor[facingMe].datum()), 
    myPeakVal(me[PEAK_V].datum()), 

在前一種情況下(ints),引用按預期工作。在浮動的情況下,編譯器給出了消息

「警告C4413:'MergeableHeight :: myEdgeVal':引用成員被初始化爲一個暫時的,在構造函數退出後不會持久化,」並且類似地爲其他兩個浮動。

用戶定義的DDBuffer類型封裝了一個具有固定數量DataDescriptors的向量 - 另一個用戶定義的類型。 DataDescriptor提供了成員函數數據(),

const float& datum()const {return _datum;} 

而DDBuffer提供[]操作,

const DatumDescriptor& operator[](int i)const {return buffer.at(i);} 
DatumDescriptor& operator[](int i) {return buffer.at(i);} //const & non-const versions 

由於寄託都返回引用,爲什麼地球上是一個在這裏被創建的臨時?特別是,總的來說,狀態變量應該反映傳遞給ctor的引用中的實際值,所以即使它保持在範圍內,我當然也不希望臨時創建它們。

我在想什麼?

+3

易讀的縮進。 –

回答

1

myEdgeVal是存儲在me中的數據的參考,它被傳遞給構造函數。由於me本身就是一個const引用,所以它可能是是一個臨時變量。如果是這樣,那麼myEdgeVal將是對構造函數完成後銷燬的對象內部的引用。

如何在代碼中構造對象?

另外,由於所有這些成員的int/double變量都是常量,所以不需要使它們成爲引用。

+0

如果他們是非臨時參考,他們的價值可能會改變其他地方... – visitor

+0

感謝您的輸入 - 我想我已經澄清了你的問題,在我對下一篇文章的迴應 - 見下文。 –

+0

正確的答案似乎是第一個發佈的 - 下午。往上看。疑難雜症通常是最簡單的事情。 –

0

當然,me是ref-const,所以是me[facingNeighbor].datum()的結果。

但是,後者是const float&,並且您試圖將其綁定到const double&,需要轉換。這會產生一個臨時的,它只存在於構造函數的範圍內。儘管它的生命週期可以在更高的堆棧幀中擴展(通過綁定到ref-const,如你所知),但它不能神奇地被帶入更低的堆棧幀。


考慮:

int foo(); 
const int& x = foo(); // valid; the result of foo() may exist as long as x does 

但是:

const int& foo() { 
    return 5;   // not valid; returning reference to local variable 
} 

int x  = foo(); 
const int& y = foo(); // same issue. 
         // the `5` simply doesn't exist; its stack frame is gone. 
+0

MergeableHeight是表達式模板庫的一部分,用於評估具有連續變化的輸入數據的模糊表達式。 MergeableHeight是在這個表達式庫中用作葉子的幾個類之一 - 它們是數據從被評估進程中輸入表達式的點。這些數據被命名爲狀態變量,它們始終處於作用域中(堆棧中的MergeableHeight下方),因此不應該因爲臨時對象而存在任何問題。 –

+0

@IGottlieb:看到我編輯的答案。確實,這不是'datum'超出範圍的結果,而是它轉換的對象。 –

10

datum()返回const float&和你的變量是一個const double&。你不能將一個轉換爲另一個,因此是暫時的。

+0

這是所有公佈的最簡單的答案,顯然是正確的答案。由於返回類型的不同,必須創建一個臨時對象,才能指出正確的類型。一個很好的提醒,不要將這些轉換視爲理所當然。我修改了DataDescriptor來保存雙打,編譯器現在很開心。謝謝一堆。 –

相關問題