Mengapa std :: konstruktor atom berperilaku berbeda di C ++ 14 dan C ++ 17

19

Saya sedang mengerjakan proyek dengan C ++ 11 dan saya mencoba kode berikut

#include <atomic>

struct A {
    std::atomic_int idx = 1;

};

int main() {
    return 0;
}

Saya mendapatkan kesalahan kompilator

error: use of deleted function 'std::__atomic_base<_IntTp>::__atomic_base(const std::__atomic_base<_IntTp>&) [with _ITp = int]'
 std::atomic_int idx = 1;
                       ^

Hasil yang sama adalah dengan C ++ 14. Ketika saya beralih ke C ++ 17 berfungsi: wandbox

Saya memeriksa perbedaan preferensi:

Tetapi tidak ada perbedaan yang didokumentasikan antara C ++ 14 dan C ++ 17. Mengapa ini bekerja dengan C ++ 17 dan tidak dengan C ++ 14?

Thomas Sablik
sumber
Kompiler / pustaka / platform standar apa yang Anda gunakan?
Victor Gubin
@ ViktorGubin saya mencoba dengan Dentang dan GCC di Linux (Wandbox). Saya mencoba berbagai versi.
Thomas Sablik
1
Anda dapat menyederhanakan MCVE menjadi hanya lokal di main(atau fungsi apa pun, tidak perlu menjadi main), bukan konstruktor struct. Dentang memberikan pesan kesalahan yang sama, menjadi lebih eksplisit bahwa itu mencoba menggunakan konstruktor salinan dihapus daripada inisialisasi atau konstruktor polos: godbolt.org/z/SBGf9w dengan libc ++
Peter Cordes
@PeterCordes Saya tidak yakin apakah kesalahan ini terkait dengan inisialisasi kelas.
Thomas Sablik
3
Mendapatkan pesan kesalahan yang sama untuk contoh minimal minimal yang dapat direproduksi membuktikan bahwa itu bukan. Saya juga tidak yakin sampai saya mencobanya.
Peter Cordes

Jawaban:

29

Karena di C ++ 17 ada RVO yang dijamin. Dalam C ++ 14 pernyataan suka Foo x = Foo(args)dan Foo x (args)secara teknis tidak sama, tetapi dalam C ++ 17.

struct Foo {
    Foo() = default;
    Foo(const Foo&) = delete;
};

int main() {
    // Works in C++17 and C++20, fails in C++14 and before
    Foo foo = Foo(); 
}

Anda dapat membaca lebih lanjut tentang ini di sini: https://en.cppreference.com/w/cpp/language/copy_elision

Khususnya bagian (since C++17):

T x = T (T (f ())); // hanya satu panggilan ke konstruktor default T, untuk menginisialisasi x

Untuk membuat kode C ++ 14 berfungsi, Anda dapat menggunakan

std::atomic_int idx { 1 };
Rinat Veliakhmedov
sumber