การลบตัวชี้ไปที่ const (T const *)


91

ฉันมีคำถามพื้นฐานเกี่ยวกับตัวชี้ const ฉันไม่ได้รับอนุญาตให้เรียกใช้ฟังก์ชันสมาชิกที่ไม่ใช่ const โดยใช้ตัวชี้ const อย่างไรก็ตามฉันได้รับอนุญาตให้ทำสิ่งนี้กับตัวชี้ const:

delete p;

สิ่งนี้จะเรียกตัวทำลายของคลาสซึ่งในสาระสำคัญคือ 'วิธีการ' ที่ไม่ใช่ const เหตุใดจึงได้รับอนุญาต เป็นเพียงการสนับสนุนสิ่งนี้หรือไม่:

delete this;

หรือมีเหตุผลอื่น?

คำตอบ:


113

เพื่อสนับสนุน:

// dynamically create object that cannot be changed
const Foo * f = new Foo;

// use const member functions here

// delete it
delete f;

แต่โปรดทราบว่าปัญหาไม่ได้ จำกัด อยู่ที่วัตถุที่สร้างแบบไดนามิก:

{
 const Foo f;
 // use it
} // destructor called here

หากไม่สามารถเรียกตัวทำลายล้างบนวัตถุ const เราไม่สามารถใช้วัตถุ const ได้เลย


21
+1 สำหรับการแก้ไขล่าสุดของคุณ ฉันคิดว่านี่คือเหตุผลที่แท้จริง ตัวทำลายอัตโนมัติเรียกวัตถุ const - เกือบจะเหมือนกับลบ f; โดยที่ f - ตัวชี้บน const
bayda

const Foo * fหรือFoo const * fไม่ใช่ตัวชี้ const ของ Foo เป็นตัวชี้ถึง const Foo Foo * const f เป็นตัวชี้ const ของ Foo
user11373693

48

วางไว้แบบนี้ - หากไม่ได้รับอนุญาตจะไม่มีวิธีลบวัตถุ const โดยไม่ใช้ const_cast

ความหมาย const เป็นสิ่งที่บ่งชี้ว่าวัตถุควรไม่เปลี่ยนรูป อย่างไรก็ตามนั่นไม่ได้หมายความว่าไม่ควรลบวัตถุ


3
ผู้ทำลายสามารถกลายพันธุ์วัตถุด้วยวิธีที่ค่อนข้างรุนแรงดังนั้นนี่ต้องเป็นการใช้คำว่า 'ไม่เปลี่ยนรูป' ที่แปลกประหลาดซึ่งฉันไม่เคยรู้มาก่อน ...
DarthGizka

1
@DarthGizka ไม่ผู้ทำลายล้างพาคุณจากสถานะที่มีวัตถุไปยังที่ที่ไม่มี C ++ ไม่ได้กำหนดวิธีการใด ๆ ในการสังเกตการทำลายโพสต์ "การกลายพันธุ์"
Caleth

@ Caleth: มาตรฐานอาจไม่อนุญาตให้คุณดูวัตถุหลังจากที่ตัวทำลายของมันทำงานจนเสร็จสิ้น แต่คุณได้รับอนุญาตให้ดูผลข้างเคียงที่เกิดจากการทำลายล้าง ดังนั้นจึงสามารถจัดเตรียมสถานการณ์เพื่อให้การกลายพันธุ์ของวัตถุ 'ไม่เปลี่ยนรูป' สามารถสังเกตได้ ในสหรัฐอเมริกาการฆาตกรรมเป็นเรื่องยากที่จะดำเนินคดีเมื่อไม่มีศพ แต่ก็ยังเป็นการฆาตกรรม (และอาจมีหลักฐานอื่นที่เพียงพอสำหรับการตัดสินลงโทษ) ความแตกต่างเดียวกัน
DarthGizka

6

ฉันไม่ได้รับอนุญาตให้เรียกใช้ฟังก์ชันสมาชิกที่ไม่ใช่ const โดยใช้ตัวชี้ const

ใช่คุณเป็น

class Foo
{
public:
  void aNonConstMemberFunction();
};

Foo* const aConstPointer = new Foo;
aConstPointer->aNonConstMemberFunction(); // legal

const Foo* aPointerToConst = new Foo;
aPointerToConst->aNonConstMemberFunction(); // illegal

คุณสับสนตัวชี้ const กับวัตถุที่ไม่ใช่ const โดยมีตัวชี้ที่ไม่ใช่ const ไปยังวัตถุ const

ต้องบอกว่า

delete aConstPointer; // legal
delete aPointerToConst; // legal

การลบอย่างใดอย่างหนึ่งถูกกฎหมายด้วยเหตุผลที่ระบุไว้ในคำตอบอื่น ๆ ที่นี่


5

ไม่ควรมองผู้สร้างและผู้ทำลายเป็น 'วิธีการ' เป็นโครงสร้างพิเศษในการเริ่มต้นและทำลายวัตถุของคลาส

'const pointer' คือการระบุว่าสถานะของวัตถุจะไม่เปลี่ยนแปลงเมื่อดำเนินการกับวัตถุในขณะที่ยังมีชีวิตอยู่


5

อีกวิธีหนึ่งในการดู: ความหมายที่ชัดเจนของตัวชี้ const คือคุณจะไม่สามารถทำการเปลี่ยนแปลงกับวัตถุที่ชี้ไปที่ซึ่งจะมองเห็นได้จากสิ่งนั้นหรือตัวชี้อื่น ๆ หรือการอ้างอิงถึงวัตถุเดียวกัน แต่เมื่อมีการทำลายวัตถุอื่น ๆ ทั้งหมดชี้ไปยังที่อยู่ที่ถูกครอบครองโดยก่อนหน้านี้ตอนนี้วัตถุที่ถูกลบจะไม่มีอีกต่อไปตัวชี้ไปยังวัตถุที่ พวกเขาจัดเก็บที่อยู่เดียวกัน แต่ที่อยู่นั้นไม่ใช่ที่อยู่ของวัตถุใด ๆ อีกต่อไป (ในความเป็นจริงอาจถูกนำกลับมาใช้เป็นที่อยู่ของวัตถุอื่นในไม่ช้า)

ความแตกต่างนี้จะเห็นได้ชัดมากขึ้นถ้าชี้ใน C ++ 0ทำตัวเหมือนอ้างอิงอ่อนแอเช่นทันทีที่วัตถุถูกทำลายตัวชี้ที่ยังหลงเหลืออยู่ทั้งหมดเพื่อมันจะได้ทันทีจะกำหนดให้ (นั่นเป็นสิ่งที่ถือว่ามีราคาแพงเกินไปในรันไทม์ที่จะกำหนดให้กับโปรแกรม C ++ ทั้งหมดและในความเป็นจริงมันเป็นไปไม่ได้ที่จะทำให้มันเชื่อถือได้ทั้งหมด)

UPDATE : อ่านย้อนหลังเก้าปีต่อมามันเป็นทนายความ ตอนนี้ฉันพบว่าปฏิกิริยาดั้งเดิมของคุณเข้าใจได้แล้ว การไม่อนุญาตให้มีการกลายพันธุ์ แต่การทำลายทิ้งนั้นเป็นปัญหาอย่างชัดเจน สัญญาโดยนัยของตัวชี้ / การอ้างอิง const คือการมีอยู่ของพวกเขาจะทำหน้าที่เป็นตัวขัดขวางการทำลายวัตถุเป้าหมายหรือที่เรียกว่าการเก็บขยะอัตโนมัติ

วิธีแก้ปัญหาตามปกติคือใช้ภาษาอื่นแทนเกือบทั้งหมด


ถ้าคุณไม่สามารถทำลายสิ่งต่างๆที่ชี้ไปยัง const ได้คุณจะจัดการกับstd::unique_ptr<const T>จุดจบของชีวิตได้อย่างไร?
Caleth

@Caleth จะไม่มีทางแก้ไขใน C ++ นั่นเป็นเพียงตัวอย่างหนึ่งของปัญหาทั่วไป: ใน C ++ ตัวแก้ไข const หมายถึง "คุณไม่สามารถกลายพันธุ์เป้าหมายได้ยกเว้นในแง่หนึ่งที่คุณสามารถทำลายมันได้อย่างสมบูรณ์และทำให้การอ้างอิงอื่น ๆ ทั้งหมดไม่ถูกต้องและเป็นแหล่งที่มาของพฤติกรรมที่ไม่ได้กำหนด" นี่คือเหตุผลที่ฉันคิดว่าคำถามประเภทนี้ควรเป็นตัวกระตุ้นให้พิจารณาภาษาอื่น ๆ มีรู UB อยู่ในนั้นซึ่งไม่สามารถแก้ไขได้โดยไม่ต้องใช้แนวทางพื้นฐานอื่น
Daniel Earwicker
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.