0

=我謹慎使用=初始化一個新的變量:使用構建新變量

MyClass my_var = MyClass(some_data); 
  1. 因爲我相信,這需要my_var首先是默認的構造,然後分配。
  2. my_var是共享內存時,這可能會導致競爭條件。

有人可以確認或否認我的恐懼嗎?原始類型的處理方式不同嗎

+2

http://stackoverflow.com/questions/1051379/is-there-a-difference-in-c-between-copy-initialization-and-direct-initializati – NPE

回答

2

因爲我認爲這需要my_var先默認構造,然後賦值。

不會。在類類型的變量聲明中使用=運算符有特殊處理。編譯器將永遠不會像您想象的那樣默認構建,然後複製變量對象。究竟反而會發生可以是:

  1. 一個臨時MyClass對象將從some_data拷貝構造,然後my_var將從臨時拷貝構造,則臨時將被釋放。因爲如果你這樣寫的:

    MyClass my_var(MyClass(some_data)); 
    
  2. 編譯器將完全優化掉臨時和簡單地直接拷貝構造從some_datamy_var。因爲如果你這樣寫的:

    MyClass my_var(some_data); 
    

    這是通常的情況下,特別是如果你這樣寫:

    MyClass my_var = some_data; 
    

    取而代之的是:

    MyClass my_var = MyClass(some_data); 
    

當my_var是共享內存,這可能會導致競爭條件。

你寫的方式,沒有。 my_var是一個函數/方法的局部變量,或者它是一個全局變量。無論哪種方式,在同一個語句中聲明和分配一個變量不是競爭條件,因爲只有在變量被構建之後才能共享該變量。如果您先聲明變量並將其分配在單獨的語句中,那麼會出現競爭條件。

+0

如果'my_var'是一個函數局部靜態? –

+0

函數本地靜態僅在第一次調用函數時才初始化一次。只有多個線程同時調用該函數時纔會出現競爭條件。但是一旦它被構造出來,就不存在更多的構造競爭條件,只是訪問(如果對象內部的邏輯不是線程安全的)。 –

+0

因此,如果函數被第一次由兩個不同的線程同時調用,那麼*就是*競爭條件。 –

1

因爲我認爲這需要my_var先默認構造,然後賦值。

my_var從不默認構建,也不是臨時的。首先構造MyClass類型的右值,使用some_data,然後調用複製構造函數(或移動構造函數,如果您在C++ 11中)構造my_var

當my_var是共享內存時,這可能會導致競爭條件。

嗯,是的。理論上它可能會導致競爭條件。

0

在您的代碼行中,只調用MyClass的複製構造函數。

如果您在代碼my_var = some_data中編寫了MyClass my_var及更高版本,則將調用MyClass::operator=(...)

爲了完成這個答案,我沒有看到共享變量在施工過程中是如何「面臨競爭條件的風險」(因爲它在構建之前不能共享)。