2016-11-22 39 views
3

我一直在尋找的bitset C++標準庫頭的頭文件。我發現,重載操作符[] operator[](size_t ndx)(在bitset類中定義)返回reference類的temproray對象。在std :: bitset :: operator []中創建的std :: bitset :: reference對象的生存期?

reference 
    operator[](size_t __position) 
{ return reference(*this,__position); } 

這個重載運算符封裝了一個位的概念。這個類的一個實例是一個實際位的代理。它可在表達式是有用的像

bitset<10> b; 
b[2] = true; 

reference類定義了重載=操作者的成員函數,使得上面的例子可以工作:

//For b[i] = __x; 
reference& 
    operator=(bool __x) 
{ 
    if (__x) 
    *_M_wp |= _Base::_S_maskbit(_M_bpos); 
    else 
    *_M_wp &= ~_Base::_S_maskbit(_M_bpos); 
    return *this; 
} 

然而,我感到困惑移到該表達式:

if (b[2]) { 
    //Do something 
} 

b[2]第一返回reference類的臨時對象,然後重載operato在該返回的臨時對象上調用r(operator bool() const)將其轉換爲bool數據類型。

// For __x = b[i]; 
operator bool() const 
{ return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) != 0; } 

如果臨時對象(具有自動存儲類對象)上堆疊創建的,則調用一個另一個函數(operator bool() const)不應該破壞由所述第一函數調用返回的臨時對象(由reference operator[](size_t __position)返回reference對象) ?

什麼是臨時對象的C和C++的壽命?

回答

2

class.temporary#4,強調的是我的。

當實現引入具有非平凡構造函數([class.ctor],[class.copy])的類的臨時對象時,它應確保爲該臨時對象調用構造函數。類似地,析構函數應該用一個不重要的析構函數([class.dtor])來臨時調用。 作爲評估完整表達式([intro.execution])的最後一步,臨時對象被銷燬(詞法)包含它們創建的點。即使評估結束於拋出異常,情況也是如此。破壞臨時對象的值計算和副作用僅與全表達式相關,而不與任何特定的子表達式相關聯。

臨時對象將在該給定表達式的最後一步被銷燬。

事實上,C++依賴於它對於這個非常常見的表達可被正確地工作:

int x = 0, y = 0, z = 0, t = 0; 
int a = x + y + z + t; 

由於x+y是臨時,x+y+z是另一個臨時。


的臨時的壽命將縮短下列規則在class.temporary#5

有三個上下文,其中的臨時被在不同的點比全表達的端部銷燬。第一個上下文是調用默認構造函數來初始化沒有相應初始值設定項([dcl.init])的數組元素。第二個上下文是在複製整個數組時複製構造函數以複製數組的元素([expr.prim.lambda],[class.copy])。在任何一種情況下,如果構造函數有一個或多個默認參數,則在構造下一個數組元素(如果有)之前,銷燬在默認參數中創建的每個臨時對象都會被排序。

,它就會被延長以下在class.temporary#6規則:

第三上下文時的引用被結合到temporary.116臨時基準被結合到其中或臨時也就是到該參考綁定的子對象的完整的對象持續基準的除了壽命:

  • 的臨時對象綁定到一個函數調用的基準參數(expr.call])持續直到包含調用的完整表達式的完成。

  • 在函數return語句([stmt.return])中返回值的臨時綁定的生命週期不會被擴展;在return語句的完整表達式的末尾臨時被銷燬。

  • 臨時綁定到新初始化程序([expr.new])中的引用,直到完成包含新初始化程序的完整表達式。

第一上下文可以看出在本例中:

struct bar { 
    bar() { std::cout << __func__ << '\n'; } 
    bar(const bar&) { std::cout << __func__ << "__\n"; } 
    ~bar() { std::cout << __func__ << '\n'; } 
}; 

struct foo { 
    foo(const bar& b = bar()) { std::cout << __func__ << '\n'; } 
}; 

int main() { 
    foo f[] = {foo(), foo()}; 
} 

上述程序應該輸出:

bar 
foo 
~bar 
bar 
foo 
~bar 

的第二上下文將被添加到C++ 17,從此程序:

struct bar { 
    bar() { std::cout << __func__ << '\n'; } 
    bar(const bar&) { std::cout << __func__ << "__\n"; } 
    ~bar() { std::cout << __func__ << '\n'; } 
}; 

struct foo { 
    foo() {} 
    foo(const foo&, const bar& b = bar()) { std::cout << __func__ << "__\n"; } 
}; 

struct foox { 
    foo f[2]; 
}; 

int main() { 
    foox fx; 
    foox yx = fx; 
} 

必須輸出:

bar 
foo__ 
~bar 
bar 
foo__ 
~bar 

對於第三種情況下,你可以找到在here答案,here

+0

有一個例外,以你的答案 - 一個臨時可以綁定到一個名爲恆定參考變量,其壽命延長至所述變量的壽命。 – Leon

+0

@Leon實際上,有三種情境,一生不一樣,我在這裏添加它 – Danh

+0

@Danh您能否詳細說明更多的課程。當代#5和課程。當代#6? – abhiarora

1

if (b[2])中的條件包括operator bool()是單個表達式,臨時表達式在表達式的整個生命週期內都是有效的。

相關問題