Pertimbangkan tiga struct
s berikut :
class blub {
int i;
char c;
blub(const blub&) {}
};
class blob {
char s;
blob(const blob&) {}
};
struct bla {
blub b0;
blob b1;
};
Pada platform tipikal di mana int
4 byte, ukuran, pelurusan dan total padding 1 adalah sebagai berikut:
struct size alignment padding
-------- ------ ----------- ---------
blub 8 4 3
blob 1 1 0
bla 12 4 6
Tidak ada tumpang tindih antara penyimpanan blub
dan blob
anggota, meskipun ukuran 1 blob
pada prinsipnya "pas" di padding blub
.
C ++ 20 memperkenalkan no_unique_address
atribut, yang memungkinkan anggota kosong yang berdekatan untuk berbagi alamat yang sama. Ini juga secara eksplisit memungkinkan skenario yang dijelaskan di atas menggunakan padding dari satu anggota untuk menyimpan yang lain. Dari cppreference (penekanan saya):
Menunjukkan bahwa anggota data ini tidak perlu memiliki alamat yang berbeda dari semua anggota data non-statis lainnya di kelasnya. Ini berarti bahwa jika anggota memiliki tipe kosong (misalnya Allocator stateless), kompiler dapat mengoptimalkannya agar tidak menempati ruang, sama seperti jika itu adalah basis kosong. Jika anggota tidak kosong, bantalan ekor di dalamnya dapat juga digunakan kembali untuk menyimpan anggota data lainnya.
Memang, jika kita menggunakan atribut ini pada blub b0
, ukuran bla
tetes 8
, sehingga blob
memang disimpan dalam blub
seperti yang terlihat pada godbolt .
Akhirnya, kita sampai pada pertanyaan saya:
Teks apa dalam standar (C ++ 11 hingga C ++ 20) yang mencegah tumpang tindih ini no_unique_address
, untuk objek yang tidak dapat disalin secara sepele?
Saya perlu mengecualikan objek trivially copyable (TC) dari atas, karena untuk objek TC, diperbolehkan std::memcpy
dari satu objek ke yang lain, termasuk sub-objek anggota, dan jika penyimpanan tumpang tindih ini akan pecah (karena semua atau sebagian dari penyimpanan untuk anggota yang berdekatan akan ditimpa) 2 .
1 Kami menghitung padding hanya sebagai perbedaan antara ukuran struktur dan ukuran semua anggota konstituennya, secara rekursif.
2 Inilah sebabnya mengapa saya memiliki salinan konstruktor yang didefinisikan: untuk membuat blub
dan blob
tidak dapat disalin secara sepele .