การเริ่มต้นของเวกเตอร์อะตอมมิก


12

พิจารณา:

void foo() {
  std::vector<std::atomic<int>> foo(10);
  ...
}

ตอนนี้เนื้อหาของ foo ใช้ได้หรือไม่ หรือฉันจำเป็นต้องวนซ้ำอย่างชัดเจนและเริ่มต้นได้อย่างไร ฉันได้ตรวจสอบ Godbolt แล้วและดูเหมือนดี แต่มาตรฐานดูเหมือนจะสับสนมากในจุดนี้

ตัวสร้าง:: เวกเตอร์ constructor บอกว่ามันแทรกอินสแตนซ์ที่แทรกค่าเริ่มต้นของstd::atomic<int>ซึ่งเป็นค่าเริ่มต้นผ่านตำแหน่งnewผ่านทางตำแหน่ง

ฉันคิดว่าผลของการกำหนดค่าเริ่มต้นนี้ใช้:

2) ถ้า T เป็นประเภทคลาสที่มีคอนสตรัคเตอร์เริ่มต้นที่ไม่ได้จัดเตรียมโดยผู้ใช้หรือลบออก (นั่นคือมันอาจเป็นคลาสที่มีคอนสตรัคเตอร์ปริยายที่กำหนดหรือเป็นค่าปริยาย) วัตถุจะเป็นศูนย์เริ่มต้นแล้ว เริ่มต้นได้เริ่มต้นถ้ามันมีตัวสร้างเริ่มต้นที่ไม่สำคัญ;

สำหรับฉันแล้วดูเหมือนว่าอะตอมมิกนั้นถูกกำหนดค่าเริ่มต้นเป็นศูนย์ ดังนั้นคำถามก็คือ a - initialisation ไม่เป็นศูนย์ของstd::atomic<int>ทำให้ผลลัพธ์เป็นวัตถุที่ถูกต้องเป็นศูนย์หรือไม่?

ฉันจะเดาว่าคำตอบคือ "ใช่ในทางปฏิบัติ แต่ยังไม่ได้กำหนดจริงๆ"?

หมายเหตุ: คำตอบนี้ยอมรับว่ามันเป็นค่าเริ่มต้นเป็นศูนย์ แต่ไม่ได้พูดจริง ๆ ถ้านั่นหมายความว่าวัตถุนั้นถูกต้อง

คำตอบ:


7

คุณถูกต้องที่จะต้องกังวล ตามมาตรฐานอะตอมมิกส์มีคอนสตรัคเตอร์เริ่มต้นที่เรียกว่าอย่างไรก็ตามมีไม่ได้เริ่มต้นเช่นนี้ นี่เป็นเพราะตัวสร้างเริ่มต้นไม่ได้เริ่มต้นอะตอม:

ค่าเริ่มต้นที่เริ่มต้นstd::atomic<T>ไม่ได้มีTวัตถุและการใช้งานที่ถูกต้องเพียงอย่างเดียวคือการทำลายและการเริ่มต้นโดย std :: atomic_init

นี่เป็นการละเมิดกฎภาษาปกติและการใช้งานบางอย่างจะเริ่มต้นอย่างไร (ตามที่คุณได้ระบุไว้)

ที่ถูกกล่าวว่าฉันขอแนะนำให้ทำตามขั้นตอนพิเศษเพื่อให้แน่ใจ 100% ว่าพวกเขาจะเริ่มต้นได้อย่างถูกต้องตามมาตรฐาน - หลังจากทั้งหมดที่คุณกำลังจัดการกับภาวะพร้อมกันที่ข้อบกพร่องอาจยากมากที่จะติดตาม

มีหลายวิธีในการหลีกเลี่ยงปัญหารวมถึงการใช้กระดาษห่อ:

struct int_atomic {
   std::atomic<int> atomic_{0};//use 'initializing' constructor
};

atomic_initหรือใช้งานจริง คุณต้องซิงโครไนซ์รอบรหัสในคำถามต่อไป
การแข่งขัน Lightness ใน Orbit

คอนสตรัคเตอร์เริ่มต้นนั้นไม่สำคัญดังนั้นจึงไม่ได้ถูกเรียก (ต่อจากคำพูดในคำถาม)
Lightness Races ใน Orbit

@LightnessRaceswithMonica ที่เป็นไปได้เช่นกันฉันแค่อยากจะเน้นเสื้อคลุม
darune

@LightnessRaceswithMonica นี่เป็นข้อยกเว้นสำหรับกฎภาษาปกติ - แม้ว่าคอมไพเลอร์บางตัวจะไม่ใช้ข้อยกเว้นนี้ ฉันไม่แน่ใจว่าคำตอบของ StoreTeller นั้นถูกต้อง 100%
darune

2

แม้ว่าคอนสตรัคค่าเริ่มต้นจะถูกเรียกใช้ (ไม่ใช่เพราะมันเล็กน้อย) มันไม่ได้ทำอะไรเลยเลย

เห็นได้ชัดว่าการเริ่มต้นเป็นศูนย์ไม่สามารถรับประกันได้ว่าจะสร้างอะตอมที่ถูกต้อง; สิ่งนี้จะใช้ได้ก็ต่อเมื่อมีโอกาสที่อะตอมที่ถูกต้องจะถูกสร้างขึ้นโดยไม่มีการเริ่มต้นสมาชิกทั้งหมด

และเนื่องจากอะตอมมิกไม่สามารถคัดลอกได้คุณจึงไม่สามารถให้ค่าเริ่มต้นในตัวสร้างเวกเตอร์

ตอนนี้คุณควรวนลูปเหนือคอนเทนเนอร์และstd::atomic_initแต่ละองค์ประกอบ หากคุณต้องการล็อคสิ่งนี้ก็ถือว่าใช้ได้เพราะคุณได้ซิงโครไนซ์การสร้างเวกเตอร์ด้วยเหตุผลเดียวกัน


@darune ฉันคิดว่าการซิงโครไนซ์ชนิดหนึ่ง;)
Lightness Races ใน Orbit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.