Pertanyaan Apakah inisialisasi nilai berfungsi untuk benda-benda atom?


Oleh kerja di sini, saya berarti itu std::atomic<T> a{} efektif nol menginisialisasi a. Saya selalu berpikir begitu dan telah praktis menggunakannya sampai ini. Sebelum menjelaskan pemahaman saya tentang ini, saya ingin menunjukkan bahwa, setidaknya, gcc dan clang melakukannya dalam praktek.

#include <cstring>
#include <atomic>
#include <iostream>

int main() {
  using atomic = std::atomic<int>;  
  auto p = (atomic*)operator new(sizeof(atomic));
  std::memset(p, -1, sizeof(atomic));
  new(p) atomic{};
  std::cout << p->load() << std::endl;
}

Hasilnya adalah 0 pada keduanya gcc dan dentang.

Berikut adalah penjelasan saya tentang mengapa ini harus bekerja (Anda mungkin berpikir sebaliknya, tentu saja). Standar mengatakan itu

Dalam definisi operasi berikut:

  • A mengacu pada salah satu tipe atom.

[...]

A::A() noexcept = default;

Efek: meninggalkan objek atom dalam keadaan terinisialisasi. [Catatan: semantik ini memastikan kompatibilitas dengan C. - catatan akhir]

Pada dasarnya mengatakan bahwa konstruktor default adalah hal yang sepele dan tidak melakukan apa-apa. Saya setuju dengan ini, tapi saya tidak melihat bagaimana ini membuat inisialisasi nilai tidak berlaku. Menurut cppref, efek inisialisasi nilai termasuk (penekanan tambang):

jika T adalah tipe kelas dengan konstruktor default yang tidak   yang disediakan pengguna atau dihapus (artinya, itu mungkin kelas dengan   implisit didefinisikan atau konstruktor default bawaan), objeknya   nol-diinisialisasi dan kemudian diinisialisasi default jika memiliki   konstruktor standar non-sepele;

std::atomic memiliki konstruktor default default, jadi objeknya adalah

  1. nol-diinisialisasi dan kemudian
  2. itu adalah default-diinisialisasi jika memiliki konstruktor default non-sepele.

Point 2 tidak berlaku di sini karena konstruktor default defaultnya sepele, tetapi saya tidak melihat pernyataan apa pun yang membuat poin 1 tidak efektif. Apakah pemahaman saya benar atau saya kehilangan sesuatu?


6
2018-03-21 08:00


asal


Jawaban:


Akhirnya inti masalah untuk kasus inisialisasi nilai masuk [dcl.init] / 7, peluru 1 dan 2:

Untuk menginisialisasi nilai objek bertipe T berarti:

  • jika T adalah tipe kelas (mungkin cv-qualified) (Klausul [class]) dengan konstruktor yang disediakan pengguna ([class.ctor]), maka konstruktor default   untuk T disebut (dan inisialisasi tidak terbentuk jika T tidak memiliki   konstruktor standar yang dapat diakses);
  • T adalah tipe kelas non-union (mungkin cv-qualified) tanpa konstruktor yang disediakan pengguna, maka objeknya adalah nol-diinisialisasi dan, jika   Konstruktor default implisit-menyatakan adalah non-sepele, itu   konstruktor disebut.
  • ...

Yang mana dari dua peluru di atas diterapkan tergantung pada c'tor yang disediakan oleh pengguna. Apa yang saya tidak ingat di komentar untuk jawaban lain, adalah seluk-beluk = default; ketika diterapkan untuk itu. Jika kita melihat definisi yang diberikan pada [dcl.fct.def.default] / 4 (penekanan saya):

Fungsi default-defaulted dan fungsi implisit yang dideklarasikan adalah   secara kolektif disebut fungsi gagal, dan implementasi harus   memberikan definisi implisit untuk mereka ([class.ctor] [class.dtor],   [class.copy]), yang mungkin berarti mendefinisikannya sebagai dihapus. Khusus   fungsi anggota disediakan oleh pengguna jika dinyatakan oleh pengguna dan tidak   secara eksplisit gagal atau dihapus pada deklarasi pertamanya. SEBUAH   fungsi yang ditetapkan secara default oleh pengguna (yaitu, secara eksplisit   gagal setelah deklarasi pertamanya) didefinisikan pada titik di mana   itu secara eksplisit gagal; jika fungsi tersebut didefinisikan secara implisit   sebagaimana dihapus, program ini tidak terbentuk. [Catatan: Mendeklarasikan fungsi sebagai   gagal setelah deklarasi pertamanya dapat memberikan eksekusi yang efisien   dan definisi ringkas saat mengaktifkan antarmuka biner yang stabil ke   basis kode berkembang. - catatan akhir]

Kami melihat bahwa default dari atomic  tidak disediakan oleh pengguna, karena dideklarasikan sebagai gagal, yang bertentangan dengan dideklarasikan dan kemudian didefinisikan sebagai gagal. Jadi, peluru kedua [dcl.init] / 7 dapat diterapkan, objeknya adalah nol-diinisialisasi, diikuti oleh (non) doa konstruktor (trivial default) yang tidak melakukan apa-apa.


5
2018-03-21 08:16