簡體   English   中英

按值傳遞參考參數

[英]Passing to a Reference Argument by Value

考慮這個簡單的程序:

vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), foo.front(), 13);

for(const auto& i : foo) cout << i << '\t';

當我寫它時我希望得到:

13 42 13 42 13 42

但相反,我得到了:

13 42 0 42 0 42

問題當然是replace通過引用獲取最后2個參數。 因此,如果它們中的任何一個碰巧處於正在操作的范圍內,結果可能是意外的。 可以通過添加臨時變量解決這個問題:

vector<int> foo = {0, 42, 0, 42, 0, 42};
const auto temp = foo.front();
replace(begin(foo), end(foo), temp, 13);

for(const auto& i : foo) cout << i << '\t';

我知道C ++ 11為我們提供了各種類型的工具,我可以簡單地將這個值強制轉換為非引用類型並傳遞內聯,而不創建臨時的嗎?

解決方案可以如下(即使你是臨時的)

template<class T>
void replace_value_of_first(std::vector<T>& v, const T& value)
{
    std::replace(v.begin(), v.end(), T(v.front()), value);
}

您可以編寫一個簡單的函數,它接受一個引用並返回一個值。 這會將引用“轉換”為值。 這確實會生成一個臨時的,但它是未命名的,並將在完整表達式的末尾銷毀。 就像是

template<typename T>
T value(const T& ref)
{
    return ref;
}

然后你可以像使用它一樣

int main()                                                   
{                                                            
    vector<int> foo = {0, 42, 0, 42, 0, 42};
    replace(begin(foo), end(foo), value(foo.front()), 13);

    for(const auto& i : foo) cout << i << '\t';                                      
}

輸出:

13  42  13  42  13  42

實例

您可以將給定值轉換為rvalue以獲得所需的效果。 下面的示例可以在不定義任何額外函數的情況下工作,只需向該值添加零即可。

vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), foo.front()+0, 13);

for(const auto& i : foo) cout << i << '\t';

或者甚至(正如Jarod42所建議的)只是一元+運算符,這是一個無操作:

vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), +foo.front(), 13);

for(const auto& i : foo) cout << i << '\t';

顯然,這些中的任何一個仍然是暫時的。 我不認為你可以擺脫這一點。

這種特殊情況下(當舊值是向量的第一個時),您可以使用rbegin()rend()來反轉替換順序。

一般來說,我不知道是否有可能以簡單的方式進行復制。

int main ()
 {
   std::vector<int> foo = {0, 42, 0, 42, 0, 42};
   std::replace(foo.rbegin(), foo.rend(), foo.front(), 13);

   for(const auto & i : foo)
      std::cout << i << '\t';

   std::cout << std::endl;

   return 0;
 }

ps:抱歉我的英語不好。

為了更明確,您可以使用int()作為構造函數來創建臨時:

replace(begin(foo), end(foo), int(foo.front()), 13);

而不是添加值。 演示

一個應該適用於任何類型的襯墊,不僅僅是數字:

replace(begin(foo), end(foo), make_pair(foo.front(),0).first, 13);

或者不創建額外的字段:

replace(begin(foo), end(foo), get<0>( make_tuple(foo.front()) ), 13);
vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), static_cast<int>(foo.front()), 13);
assert(equal(begin(foo), end(foo), begin({13, 42, 13, 42, 13, 42})));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM