2017-02-24 32 views
3
#include<iostream> 
#include<utility> 
#include<tuple> 
#include<functional> 
using namespace std; 
int main() 
{ 
    int i = 0; 
    auto p = make_pair(ref(i), ref(i++)); 
    p.first++; 
    p.second++; 
    cout << "i = " << i << endl; 
} 

例如,如果我使用ref()這樣,編譯器會說爲何我使用已刪除的功能 '無效的std :: REF(常量_TP &&)[與_TP = INT]'

use of deleted function 'void std::ref(const _Tp&&) [with _Tp = int]'

但是,如果我的代碼是繼

#include<iostream> 
#include<utility> 
#include<tuple> 
#include<functional> 
using namespace std; 
int main() 
{ 
    int i = 0; 
    auto p = make_pair(ref(i), ref(++i)); 
    p.first++; 
    p.second++; 
    cout << "i = " << i << endl; 
} 

我將會成功輸出i = 3,所以我不明白爲什麼我得到這麼不同的答案。

+12

'ref(i ++)' - 引用臨時,'++ i'返回原始變量的引用 – xinaiz

+0

@BlackMoses:請在答案部分中回答。 –

+0

我非常感謝,經過反思後,我認爲ref(i ++)是一個臨時的參考非常合理 – Yyh

回答

7

std::ref需要一個變量,併爲您提供一些行爲,如同對該變量的引用。

i++不是一個變量;這是一個暫時的。這是因爲增量後的工作原理;原始值會遞增,但表達式的計算結果爲舊的值,並且需要一個臨時值來保存該舊值以便您可以讀取它。

std::ref不允許你使用臨時的,以避免這樣的錯誤。這將是一個懸而未決的參考,否則。

++i,另一方面,只是讓你回到原來的變量,所以你可以參考一下就好了。

但是,您不能像這樣將i++i彼此相鄰;這兩個表達式相對於彼此被不確定地排序(或某物)。不惜一切代價避免這種代碼。

+2

我擡頭看了序列,在C++ 14中它是UB由於無序的論證副作用,但在C + +17它將被不確定地排序,也就是'ref(i)'可能在'++ i'的副作用完成之前或之後讀取'i',但它不是UB。後面的文本是在N4606。 [參考](http://stackoverflow.com/a/39238441/1505939) –

+0

我不確定*這個特殊情況*是UB,因爲i的值不用於獲取引用的子表達式中到它。一般的觀點是正確的 – Caleth

+0

當你說矢量 myvec {1,2,3}; REF(myvec會[0])。你會得到:錯誤:使用已刪除的函數'void std :: ref(const _Tp &&) –

相關問題