有人可以向我解釋爲什麼R值的輸出與L值不同?R值和L值的輸出不同。爲什麼?
#include <iostream>
#include <vector>
using namespace std;
template<typename Ct>
struct ct_wrapper {
Ct&& ct; // R or L ref
explicit ct_wrapper(Ct&& ct)
: ct(std::forward<Ct>(ct)) { std::cout << this->ct[1];};
};
int main() {
// L-val
vector<int> v{1,2,3};
ct_wrapper<vector<int>&> lv(v);
cout << endl << lv.ct[0] << lv.ct[1] << lv.ct[2] << endl;
// R-val
ct_wrapper<vector<int>&&> rv(vector<int>{1,2,3});
cout << endl << rv.ct[0] << rv.ct[1] << rv.ct[2] << endl;
}
輸出(同爲gcc48和clang32):
2
123
2
003
回答
這是我與約翰內斯·紹布聊天有點埋沒,所以我把它放在這裏。
當臨時向量初始化r-value-ref成員變量rv.ct
時,由於存在特殊的異常,臨時生存期不會延長:[class.temporary] p5:「臨時綁定到構造函數的ctor-initializer中的引用成員(12.6.2)一直存在,直到構造函數退出。「
+1(還有其他所有),但我仍然感到困惑。我認爲當臨時綁定到r值ref時,它的壽命延長到r值變量的壽命。沒有?我們還有'rv.ct'。 –
@LeonidVolnitsky有一個特殊的例外(因爲否則編譯器不可能得到這個權利):[class.temporary] p5:「臨時綁定到構造函數的ctor-initializer中的引用成員(12.6.2)直到 構造函數退出。「 (我想說的是參考文獻不是一定要臨時的,而是要參考一個臨時的,但我沒有在標準中看到這種區別。) – hvd
@ hvd right。實際上,這個區別並不在條款類當中。該條款涉及表達式直接具有該屬性的情況。 (如果標準中的文本顯示「創建臨時值...」,則右值直接攜帶該臨時屬性)。其他規則指的是臨時*對象*,而不是以這種方式標記的表達式,所以需要總是仔細閱讀封閉的上下文以知道是什麼意思(恕我直言,規範在這裏很差,它可以做得更清楚,見http: //www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299)。 –