[英]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:抱歉我的英語不好。
一個應該適用於任何類型的襯墊,不僅僅是數字:
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.