簡體   English   中英

將數據移入函數然后返回到它來自何處時,是否存在任何未定義的行為問題?

[英]Are there any undefined behavior issues when moving data into a function and then back out to where it came from?

考慮以下功能:

std::vector<int> pushIt(std::vector<int> v){
    v.push_back(10);
    return v; 
}

int main(){
    std::vector<int> vec;
    vec = pushIt(std::move(vec));
}

我的假設是向量移動到函數中,修改並移回其原始位置。 這應該導致類似的行為,因為它作為非const引用傳遞。 這似乎是非常有效的行為,但同事擔心未定義的行為。 這里有什么我想念的嗎?

我想這樣做是因為當前的功能

void currentPushIt(std::vector<int>& v){
    v.push_back(10);
}

在代碼審查中導致了很多問題,因為人們忽略了對currentPushIt(v)的無辜調用可能使迭代器無效的事實。 讓他們寫v=pushIt(std::move(v))應該喚醒他們不會犯同樣的錯誤。

根據1.9p15,在執行函數體之前,對與參數關聯的值計算和副作用進行排序。 因此,當您輸入pushIt ,源vec已被移除。 然后在執行pushIt之后對賦值進行pushIt ,因為您實際上正在調用用戶定義的運算符vector::operator=

vec.operator=(       // sequenced after
    pushIt(          // the evaluation of this, which is sequenced after
        std::move(   // the evaluation of this
            vec)))

所以你的代碼很好。

你的同事擔心是沒有理由的,所示的片段不會受到不確定行為的影響


由於std::vector是一個類,所寫的片段等同於下面的內容,因為函數參數在調用函數之前必須有一個值,它相當於首先調用std::move ,然后是pushIt ,后來是vec.operator=

以這種方式查看時,很明顯,編寫這樣的代碼實際上是安全的。

vec.operator= (pushIt (std::move (vec));

一般來說

a = do_something (a);

我遇到過那些擔心這些片段的開發者,因為=不是序列點 ; 如果do_something修改a ,左側會發生什么?

長話短說; 沒關系。 即使我們不知道將評估左側和右側的順序,但在正確性方面它是明確定義的。


=的左側是左值 ,可以看作某個值最終的位置。 無論存儲在此位置的值,實際位置將始終相同。

在這種情況下,右側將從vec移開。 這無疑會改變vec的價值,但它不會改變vec的位置; 所以右側的結果將被正確地分配到它應該的位置。

注意:實際分配是按順序排列的,在發生這種情況之前必須評估lhsrhs (即在將rhs的值分配給lhs的位置產量之前),但是未設置lhsrhs的評估順序在石頭上。

將數據移入函數然后返回到它來自何處時,是否存在任何未定義的行為問題?

沒有。

函數參數被評估為“在序列之前”功能評估。 分配是在“右側評估”之后“排序”。

暫無
暫無

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

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