destructor ของอ็อบเจ็กต์โลคัลภายในลูปรับประกันว่าจะถูกเรียกก่อนการวนซ้ำครั้งถัดไปหรือไม่?


11

เมื่อฉันมีลูปและภายในลูปนี้สร้างตัวแปรสแต็กใหม่ (ไม่จัดสรรในฮีปและตัวแปรที่เก็บไว้ที่ประกาศไว้ในเนื้อความลูป) เป็นตัวทำลายของวัตถุนี้รับประกันว่าจะถูกเรียกก่อนเริ่มการทำซ้ำครั้งถัดไปหรืออาจ วนรอบการคลี่คลายโดยคอมไพเลอร์เปลี่ยนอะไรบางอย่างเกี่ยวกับที่?


1
วนรอบการคลี่คลายต่อ seจะไม่เปลี่ยนลำดับของการดำเนินการ อย่างไรก็ตามการวนซ้ำแบบวนซ้ำสามารถทำได้
Adrian Mole

คำตอบ:


8

จากn4800:

ขอบเขตบล็อก §6.3.3 :

ชื่อที่ประกาศในบล็อก (8.3) เป็นชื่อท้องถิ่นในบล็อกนั้น มันมีขอบเขตบล็อก ขอบเขตที่เป็นไปได้เริ่มต้นที่จุดประกาศ (6.3.2) และสิ้นสุดที่จุดสิ้นสุดของบล็อก ตัวแปรที่ประกาศ ณ ขอบเขตบล็อกเป็นตัวแปรโลคัล

§10.3.6 Destructors :

destructor ถูกเรียกใช้โดยปริยาย [... ] เมื่อบล็อกที่วัตถุถูกสร้างออก (8.7)

§4.1.1 เครื่องบทคัดย่อ :

บทบัญญัตินี้บางครั้งเรียกว่ากฎ“ ราวกับถ้า” เพราะการดำเนินการมีอิสระที่จะเพิกเฉยต่อข้อกำหนดใด ๆ ของเอกสารนี้ตราบใดที่ผลลัพธ์นั้นราวกับว่าข้อกำหนดได้รับการปฏิบัติตามเท่าที่สามารถพิจารณาได้จากพฤติกรรมที่สังเกตได้ของ โปรแกรม

[เน้นเหมือง]

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


1
ไม่มีสิ่งใดในนั้นที่เรียกว่า destructor
สิ้นเชิง

2
@ เริ่มต้นสิ่งที่ทำให้พวกเขาทำเช่นนี้เป็นกฎราวกับ มาตรฐานระบุพฤติกรรมของเครื่องที่เป็นนามธรรมเท่านั้น ไม่แน่ใจว่าจำเป็นต้องระบุรายละเอียดทั้งหมดในคำตอบที่นี่หรือไม่
Max Langhof

2
@ เริ่มต้นนี่คือ IMO ที่ไม่เกี่ยวข้องกับคำถาม คุณอาจจะบอกว่า destructors อาจถูก inline และดังนั้นจึงไม่called เลย หรือถ้าพวกเขาอย่างมีประสิทธิภาพ (ราวกับว่ากฎ) ไม่ทำอะไรเลยอาจจะไม่มีการชุมนุมสำหรับ destructors ที่สร้าง
Daniel Langr

2
@ เริ่มต้นดูกฎ“ as-if” คืออะไร? .
Daniel Langr

2
@ เริ่มต้นที่ไหนถูกกำหนดอะไร ? โปรดทราบว่าการอภิปรายนี้อยู่นอกหัวข้อของคำถาม คุณอาจถามคำถามแยกต่างหากเกี่ยวกับปัญหานี้
Daniel Langr

8

ใช่. การมองเห็นได้ง่ายขึ้นเมื่อคุณพิจารณา "บล็อก" ที่คุณประกาศตัวแปรคือระหว่างวงเล็บปีกกาคู่ใด ลูปเป็นบล็อกในตัวมันเองและเมื่อมันมาถึงวงเล็บปิดก่อนการทำซ้ำครั้งถัดไป destructors ทั้งหมดของตัวแปรหน่วยเก็บข้อมูลอัตโนมัติที่ประกาศในลูปจะถูกเรียก

อาจลูปที่คลี่คลายโดยคอมไพเลอร์เปลี่ยนบางสิ่งบางอย่างเกี่ยวกับที่?

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


2
+1 สำหรับกฎง่ายๆเมื่อเขียนโค้ดหนึ่งไม่ควรกังวลเกี่ยวกับคอมไพเลอร์ภายใน กำลังจะเพิ่มบางสิ่งในจิตวิญญาณเดียวกันกับคำตอบของฉัน แต่ตอนนี้มันมีอยู่แล้ว
idclev 463035818

การคัดลอกและ RVO เปลี่ยนพฤติกรรมของโปรแกรมใช่หรือไม่
Jean-Baptiste Yunès

@ Jean-BaptisteYunèsพวกเขาสามารถอย่างไรก็ตามมาตรฐานให้พวกเขาด้วย[class.copy.elision]
ChrisMM

ไม่ได้เป็นเพียงคู่ของการจัดฟัน คุณสามารถเขียนfor(...) X x{};และxวัตถุจะถูกสร้างขึ้น + ถูกทำลายในการทำซ้ำแต่ละครั้ง การสาธิตสด ส่วนมาตรฐานที่เกี่ยวข้องคือstmt.iter / 2
Daniel Langr

@DanielsaysreinstateMonica ตาม§9.5.2 [stmt.iter]มันเทียบเท่ากันหมด (เน้นการทำเหมืองแร่): "ถ้า substatement ในประโยค iteration-statement เป็นคำสั่งเดียวและไม่ใช่ compound-statement มันเหมือนกับว่ามันถูกเขียนใหม่ให้เป็นคำสั่งผสมที่มี ข้อความต้นฉบับ ". ในสาระสำคัญโดยมีหรือไม่มีวงเล็บปีกกาสำหรับคำสั่งเดียวหมายถึงสิ่งเดียวกันและวงเล็บปีกกามีนัย ฉันละเว้นมันเพื่อความชัดเจน
JBL

2

ตัวทำลายถูกเรียกใช้สำหรับการวนซ้ำทุกครั้ง ดังนั้นในบางกรณีการประกาศตัวแปรภายนอกลูปแทนการวนซ้ำนั้นทำได้เร็วกว่า สมมติว่ากรณีต่อไปนี้:

std::string temp;
for(int i = 0; i < 10; ++i){
    temp = arr[i];
    doSomething(temp);
}

destructor ไม่ถูกเรียกเมื่อใช้การวนซ้ำ tempมันเป็นเพียงแค่การแทนที่

แต่ถ้าคุณใช้std::string temp = arr[i]Constructor และ Destructor จะมีการเรียกซ้ำแต่ละครั้ง ฉันคิดว่านี่เพิ่ม bit runtime ในกรณีที่คุณมีการวนซ้ำที่ดำเนินการบ่อยมาก


โปรดทราบว่า destructors ที่ถูกเรียกหรือไม่นั้นไม่ใช่แค่คำถามเกี่ยวกับประสิทธิภาพ เมื่อคุณมีประเภท RAII คุณต้องการให้ destructor ถูกเรียกใช้ในการวนซ้ำทุกครั้ง
idclev 463035818

ไม่แน่ใจว่าเป็นเรื่องจริง ตัวทำลายของเนื้อหา 'temp' ไม่ได้ถูกถือครองจากการทำซ้ำก่อนหน้านี้ถูกเรียกว่าถูกต้องเมื่ออุณหภูมิได้รับการกำหนดค่าใหม่ด้วยค่าใหม่หรือไม่
user1282931

ฉันก็ไม่แน่ใจเหมือนกัน 100% แก้ไขคำตอบของฉันหากคุณพบสิ่งผิดปกติ :)
Julian Schnabel


0

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.