ตัวชี้ทางคณิตศาสตร์ในหน่วยเก็บข้อมูลที่จัดสรรอนุญาตตั้งแต่ C ++ 20 หรือไม่


10

ใน C ++ 20 มาตรฐานมันก็บอกว่าประเภทอาร์เรย์เป็นประเภทอายุการใช้งานโดยปริยาย

หมายความว่าอาเรย์สำหรับประเภทอายุการใช้งานที่ไม่แน่นอนสามารถสร้างได้หรือไม่? การสร้างอาเรย์โดยนัยจะไม่ทำให้เกิดการสร้างองค์ประกอบของอาเรย์?

พิจารณากรณีนี้:

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to object" (which object?)
std::string * sptr = std::launder(static_cast<std::string*>(ptr));
//pointer arithmetic on not created array elements well defined?
new (sptr+1) std::string("second element");

รหัสนี้ไม่ใช่ UB อีกต่อไปตั้งแต่ C ++ 20 หรือไม่


อาจจะเป็นวิธีนี้จะดีกว่า

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to the array of 10 std::string" 
std::string (* sptr)[10] = std::launder(static_cast<std::string(*)[10]>(ptr));
//pointer arithmetic on an array is well defined
new (*sptr+1) std::string("second element");

1
ฉันเพิ่งทำการค้นหาผ่าน (ฉบับร่าง) C ++ 20 มาตรฐานและไม่พบสิ่งใดที่อธิบายว่าอาร์เรย์เป็น "ประเภทอายุการใช้งานโดยนัย" (และใช่ฉันค้นหาการเปลี่ยนแปลง) โปรดระบุรายละเอียดเพิ่มเติมเกี่ยวกับการอ้างสิทธิ์ของคุณ (เช่นส่วนและข้อในมาตรฐาน) ยากที่จะตอบคำถามของคุณโดยไม่สามารถค้นหาแหล่งที่มาบริบทที่เกี่ยวข้องได้โดยลำพัง
ปีเตอร์

1
@Peter : eel.is/c++draft/basic.types#9ประโยคสุดท้าย
geza

ฉันกำลังดู PDF open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf (เห็นได้ชัดว่าเป็นฉบับร่างการทำงานล่าสุด) และไม่มีแม้แต่ประโยคนั้น ดูเหมือนว่าคุณจะต้องค้นหาความหมายของ "ชีวิตโดยปริยาย" ด้วย ฉันสงสัยว่าลิงก์ของคุณอาจเลือก "การแก้ไขที่กำลังดำเนินการ" ซึ่งยังไม่ได้ทำให้กลายเป็นฉบับร่างที่ใช้งานได้
ปีเตอร์

1
@Peter การเปลี่ยนแปลงเป็นผลมาจากการรวมP0593เป็นมาตรฐานจากการประชุมที่ปราก พวกเขายังไม่ได้เผยแพร่ร่างผลลัพธ์ แต่คุณสามารถเห็นข้อความที่ผสานในการกระทำนี้
walnut

คำตอบ:


3

หมายความว่าอาเรย์สำหรับประเภทอายุการใช้งานที่ไม่แน่นอนสามารถสร้างได้หรือไม่?

ใช่.

การสร้างอาเรย์โดยนัยจะไม่ทำให้เกิดการสร้างองค์ประกอบของอาเรย์?

ใช่.

นี่คือสิ่งที่ทำให้สามารถstd::vectorนำไปใช้งานได้ใน C ++ ธรรมดา


คุณสามารถยืนยันด้วยstd::launder(static_cast<std::string*>(ptr))ว่าไม่ได้ส่งคืนพอยน์เตอร์ไปยังองค์ประกอบแรกของอาเรย์เพราะมันไม่ได้อยู่ในช่วงอายุการใช้งานของมัน แต่มันจะstd::launder(static_cast<std::string(*)[10]>(ptr))ส่งกลับพอยน์เตอร์ไปยังอาเรย์เพราะอาเรย์นั้นอยู่ภายในช่วงชีวิต
Oliv

ดูเหมือนว่าถูกต้องสำหรับฉัน
TC

@Oliv และฉันคิดว่าstd::launderไม่จำเป็นจริง ๆ เพราะeel.is/c++draft/intro.object#11รับประกันว่าptrจะชี้ไปที่อาร์เรย์หรือไม่
วอลนัท

@ วอลนัตฉันพลาดนั่น ดังนั้นstatic_castการstd::string (*) [10]ควรจะเพียงพอ! เท็กซัส
Oliv

@Oliv แต่ฉันเดาคำถามนั้นจะกลายเป็นว่าตัวอย่างแรกของคุณโดยไม่ต้องstd::launderจะถูกกำหนดไว้อย่างดี ไม่มีstd::stringวัตถุที่จะชี้ไป แต่ptrสามารถชี้ไปที่อาร์เรย์เพื่อที่ร่ายสแตติกจะปล่อยค่าไม่เปลี่ยนแปลงและsptrจะชี้ไปที่อาร์เรย์เช่นกัน ด้วยstd::launderมันเป็น UB เพียงเพราะstd::launderความต้องการของ
walnut
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.