พิจารณาสามstruct
s ต่อไปนี้:
class blub {
int i;
char c;
blub(const blub&) {}
};
class blob {
char s;
blob(const blob&) {}
};
struct bla {
blub b0;
blob b1;
};
บนแพลตฟอร์มทั่วไปที่int
มีขนาด 4 ไบต์ขนาดการจัดตำแหน่งและระยะห่างรวม1เป็นดังนี้:
struct size alignment padding
-------- ------ ----------- ---------
blub 8 4 3
blob 1 1 0
bla 12 4 6
ไม่มีการทับซ้อนกันระหว่างที่เก็บของblub
และblob
สมาชิกแม้ว่าขนาด 1 blob
สามารถทำได้ในหลักการ "พอดี" ในการเติมblub
เต็ม
C ++ 20 แนะนำno_unique_address
คุณสมบัติซึ่งอนุญาตให้สมาชิกว่างที่อยู่ติดกันแบ่งปันที่อยู่เดียวกัน นอกจากนี้ยังช่วยให้สถานการณ์ที่อธิบายไว้ข้างต้นอย่างชัดเจนของการใช้การขยายของสมาชิกคนหนึ่งเพื่อเก็บอีก จากcppreference (เน้นที่เหมือง):
บ่งชี้ว่าสมาชิกข้อมูลนี้ไม่จำเป็นต้องมีที่อยู่ที่แตกต่างจากสมาชิกข้อมูลที่ไม่คงที่อื่น ๆ ของระดับเดียวกัน ซึ่งหมายความว่าหากสมาชิกมีประเภทที่ว่างเปล่า (เช่นตัวจัดสรรแบบไร้สถานะ) ผู้รวบรวมอาจปรับให้เหมาะสมเพื่อไม่ให้มีที่ว่างเช่นเดียวกับว่าเป็นฐานที่ว่างเปล่า หากสมาชิกไม่ว่างเปล่าการเติมส่วนท้ายใด ๆ ในนั้นอาจถูกนำมาใช้ซ้ำเพื่อจัดเก็บข้อมูลสมาชิกอื่น
อันที่จริงถ้าเราใช้แอตทริบิวต์นี้ในblub b0
ขนาดของbla
หยดไป8
ดังนั้นblob
จะถูกเก็บไว้แน่นอนในblub
เท่าที่เห็นใน godbolt
ในที่สุดเราก็มาถึงคำถามของฉัน:
ข้อความใดในมาตรฐาน (C ++ 11 ถึง C ++ 20) ป้องกันการซ้อนทับนี้โดยไม่มีno_unique_address
สำหรับวัตถุที่ไม่สามารถคัดลอกได้เล็กน้อย
ฉันต้องแยกวัตถุที่คัดลอกได้เล็กน้อย (TC) จากด้านบนเพราะสำหรับวัตถุ TC มันได้รับอนุญาตstd::memcpy
จากวัตถุหนึ่งไปยังวัตถุอื่นรวมถึง subobjects สมาชิกและถ้าที่เก็บซ้อนทับสิ่งนี้จะทำลาย (เพราะทั้งหมดหรือบางส่วนของหน่วยเก็บข้อมูล สำหรับสมาชิกที่อยู่ติดกันจะถูกเขียนทับ) 2 .
1เราคำนวณการเติมเต็มเพียงแค่ความแตกต่างระหว่างขนาดโครงสร้างและขนาดของส่วนประกอบที่เป็นสมาชิกทั้งหมดซ้ำ
2นี่คือเหตุผลที่ผมได้สำเนาก่อสร้างที่กำหนดไว้เพื่อให้blub
และblob
ไม่copyable นิด