C ++ semantics ของ `static const` เทียบกับ` const '


149

ใน C ++ โดยเฉพาะความแตกต่างระหว่าง semantic คืออะไร:

static const int x = 0 ;

และ

const int x = 0 ;

สำหรับstaticเป็นตัวเชื่อมโยงและตัวระบุคลาสหน่วยเก็บข้อมูล (เช่นภายในและภายนอกฟังก์ชัน)


7
staticน่าจะเป็นคำหลักที่มากเกินไปใน C ++ ความหมายของรหัสของคุณแตกต่างกันอย่างมากขึ้นอยู่กับว่าอยู่ในขอบเขตเนมสเปซที่ขอบเขตคลาสหรือที่ขอบเขตฟังก์ชัน คุณอาจต้องการชี้แจงว่า
sbi

1
@sbi: ฉันคิดว่าฉันทำไปแล้ว ขอบเขตของฟังก์ชัน (ซึ่งเป็นตัวระบุคลาสหน่วยเก็บข้อมูล) และขอบเขตไฟล์ (ซึ่งเป็นตัวระบุลิงก์) สมาชิกของคลาสและตัวแปรที่กำหนดขอบเขตของ namespace โดยเฉพาะนั้นไม่ได้กังวลกับฉันในส่วนที่เกี่ยวกับคำถามนี้ แต่ถ้าใครรู้สึกว่ามีความแตกต่างที่น่าสนใจ
Clifford

@Clifford: ฉันขอโทษที่ฉันมองข้ามคำสุดท้ายเหล่านั้น อย่างไรก็ตามสิ่งนี้เผยให้เห็นความเข้าใจผิดในส่วนของคุณ: ใน C ++ ขอบเขตไฟล์คือขอบเขตเนมสเปซ หากคุณประกาศอะไรก็ตามที่อยู่ด้านนอกของเนมสเปซใด ๆ มันจะเป็นของเนมสเปซส่วนกลาง (และสามารถเข้าถึงได้ผ่านทางส่วนนำหน้า::โดยไม่มีตัวระบุด้านหน้า) ฉันไม่ได้ตระหนักถึงความแตกต่างที่มีความหมายระหว่าง namespace ทั่วโลกและ namespace ใด ๆ ซ้อนกันอยู่ในนั้น แน่นอนว่าไม่มีstaticวัตถุใด ๆ ที่เกี่ยวข้อง
sbi

1
การเชื่อมโยงแตกต่างจากการมองเห็นโดยใช้พวกเขาสลับกันคุณจะสร้างความสับสนให้กับคนที่คุณคุยด้วยและอาจเป็นตัวคุณเอง
Ben Voigt

1
@Ben, @sbi: ฉันไม่ได้ตั้งใจจะแนะนำขอบเขตไฟล์และการเชื่อมโยงแบบสแตติกเหมือนกัน แต่การเชื่อมโยงแบบคงที่หมายถึงขอบเขตไฟล์ ในขอบเขตนี้(หรือทัศนวิสัย) เป็นคุณลักษณะของการเชื่อมโยงแบบสแตติกและภายนอกไม่ใช่คำพ้องความหมายสำหรับทั้งสอง ฉันรู้สึกว่าคำถามดั้งเดิมยังคงชัดเจนและก่อตัวได้ดีและเราเพียง แต่พูดถึงความคิดเห็นที่ตอบสนองต่อคำพูดที่ค่อนข้างจะทำให้เอสบีไอ เรากำลังพูดถึงความหมายที่ไม่ชัดเจนของภาษาอังกฤษที่นี่มากกว่าความเข้าใจของฉันดังนั้นฉันคิดว่าเราสามารถหยุด
Clifford

คำตอบ:


128

ที่ขอบเขตไฟล์ไม่มีความแตกต่างใน C ++ constทำให้การเชื่อมโยงภายในเป็นค่าเริ่มต้นและตัวแปรส่วนกลางทั้งหมดมีอายุการใช้งานคงที่ แต่ตัวแปรแรกมีพฤติกรรมเหมือนกันใน C ดังนั้นอาจเป็นเหตุผลที่ดีที่จะใช้

ภายในฟังก์ชั่นรุ่นที่สองสามารถคำนวณได้จากพารามิเตอร์ ใน C หรือ C ++ ไม่จำเป็นต้องมีค่าคงที่เวลาคอมไพล์เหมือนภาษาอื่น ๆ ที่ต้องการ

ภายในชั้นเรียนนั้นเป็นสิ่งเดียวกับฟังก์ชั่น อินสแตนซ์constค่าสามารถคำนวณได้ในctor-initializer รายการ A static constถูกตั้งค่าในระหว่างการเริ่มต้นการเริ่มต้นและยังคงไม่เปลี่ยนแปลงสำหรับส่วนที่เหลือของโปรแกรม (หมายเหตุ: รหัสสำหรับstaticสมาชิกมีลักษณะแตกต่างกันเล็กน้อยเนื่องจากการประกาศและการเริ่มต้นจะถูกแยกออกจากกัน)

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


1
มีอะไรเรียกว่าขอบเขตไฟล์หรือไม่ ฉันเพิ่งตรวจสอบ $ 3.3 และฉันคิดว่าใกล้เคียงที่สุดคือ 'ขอบเขต namespace' ความเข้าใจของฉันถูกต้องหรือไม่ ขอบเขตไฟล์มาตรฐาน C ++ 03 กล่าวถึงเฉพาะในภาคผนวก
Chubsdad

2
ฉันขอแนะนำให้ขอบเขตไฟล์เป็นสิ่งประดิษฐ์ของตัวเชื่อมโยงมากกว่าตัวแปลดังนั้นอาจไม่ได้รับความสนใจมากในมาตรฐานภาษา อาจเป็น "ขอบเขตหน่วยการรวบรวม" อย่างเคร่งครัด
Clifford

8
+1 สำหรับวลี "const หมายถึงอ่านอย่างเดียวไม่ใช่ค่าคงที่" เช่น "คอมไพเลอร์ถ้าคุณเห็นใครบางคนพยายามที่จะแก้ไขสิ่งนี้ให้ทำเสียงดังเห่ามาก" นี่คือเหตุผลที่สิ่งที่สามารถ const & ระเหยในเวลาเดียวกัน
ด่าน

5
มันเป็น "คอมไพเลอร์ถ้าคุณเห็นฉันพยายามที่จะแก้ไขสิ่งที่ const นี้ (หรือให้คนอื่นได้รับอนุญาตให้ทำ)" เห่าเสียงดังมาก ในบริบทส่วนใหญ่constนำไปใช้กับมุมมองของตัวแปรและไม่ใช่ตัวแปรเองคนอื่นสามารถมีconstมุมมองที่ไม่เหมือนกันของตัวแปรเดียวกันและคอมไพเลอร์จะค่อนข้างเงียบเมื่อพวกเขาปรับเปลี่ยน
Ben Voigt

1
@Ben: เพื่อให้ชัดเจน C + 0x ไม่ได้ลบการใช้งานนั้นโดยเฉพาะconstแต่constexprสามารถใช้งานใหม่ได้แทน (และในสถานการณ์อื่น ๆ ด้วย) ที่จริงแล้วมาตรฐาน C ++ 0x จะขยายความสามารถในการใช้งานconstในสถานการณ์นั้นไปสู่ ​​"ประเภทตัวอักษร" ที่ไม่สำคัญเช่นกัน ฉันคิดว่าฉันต้องการใช้constexprสำหรับกรณีเหล่านี้เนื่องจากคุณจะเลิกใช้งานร่วมกับคอมไพเลอร์ pre-C ++ 0x ได้
Michael Burr

4

แบบร่างมาตรฐาน C ++ 17 constหมายถึงstaticขอบเขตไฟล์

นี่คือคำพูดสำหรับสิ่งที่กล่าวถึงที่: https://stackoverflow.com/a/3709257/895245

C ++ 17 n4659 ร่างมาตรฐาน 6.5 "โปรแกรมและการเชื่อมโยง":

3 ชื่อที่มีขอบเขตเนมสเปซ (6.3.6) มีการเชื่อมโยงภายในหากเป็นชื่อ

  • (3.1) - ตัวแปรฟังก์ชั่นหรือฟังก์ชั่นแม่แบบที่มีการประกาศอย่างคงที่; หรือ,
  • (3.2) - ตัวแปรที่ไม่ใช่แบบอินไลน์ของประเภท const ที่ไม่ผ่านการลบเลือนที่ไม่ได้ประกาศอย่างชัดแจ้งภายนอกหรือประกาศก่อนหน้านี้ว่ามีการเชื่อมโยงภายนอก หรือ
  • (3.3) - ข้อมูลสมาชิกของสหภาพที่ไม่ระบุชื่อ

ภาคผนวก C (ข้อมูล) ความเข้ากันได้ C.1.2 ข้อ 6: "แนวคิดพื้นฐาน" ให้เหตุผลว่าทำไมสิ่งนี้จึงเปลี่ยนจาก C:

6.5 [ยัง 10.1.7]

เปลี่ยนแปลง: ชื่อของขอบเขตไฟล์ที่ประกาศ const อย่างชัดเจนและไม่เปิดเผยภายนอกอย่างชัดเจนมีการเชื่อมโยงภายในขณะที่ C จะมีการเชื่อมโยงภายนอก

เหตุผล: เนื่องจากวัตถุ const อาจถูกใช้เป็นค่าระหว่างการแปลใน C ++ คุณสมบัตินี้เรียกร้องให้โปรแกรมเมอร์จัดเตรียม initializer อย่างชัดเจนสำหรับวัตถุ const แต่ละตัว คุณลักษณะนี้ช่วยให้ผู้ใช้สามารถวางวัตถุ const ในไฟล์ต้นฉบับที่รวมอยู่ในหน่วยการแปลมากกว่าหนึ่งหน่วย

ผลต่อคุณสมบัติดั้งเดิม: เปลี่ยนความหมายของคุณสมบัติที่กำหนดไว้อย่างดี

ความยากลำบากในการแปลง: การแปลงความหมาย

ใช้กันอย่างแพร่หลาย: ไม่ค่อย

ดูเพิ่มเติม: เหตุใด const จึงแสดงถึงการเชื่อมโยงภายในใน C ++ เมื่อไม่ได้อยู่ใน C

สิ่งที่คุณน่าจะต้องการทำแทนส่วนหัว

อธิบายรายละเอียดได้ที่: 'const static' หมายถึงอะไรใน C และ C ++

  • ก่อน C ++ 17: externในส่วนหัว, คำจำกัดความในไฟล์ cpp
  • โพสต์ C ++ 17: ตัวแปรอินไลน์ที่ส่วนหัว

ขอบคุณแม้ว่าฉันไม่คิดว่านี่เป็นโอกาสใน C ++ 17 เมื่อเทียบกับ C ++ 98 และคำถามถูกถามในปี 2010 นอกจากนี้คำตอบของคุณจะเกี่ยวข้องกับ static เป็นตัวระบุลิงก์ (ที่ขอบเขตเนมสเปซ) เท่านั้น และคำถามที่ถามโดยเฉพาะเกี่ยวกับความหมายในบริบทที่แตกต่างกัน
Clifford

@Clifford ใช่เก่ากว่า C ++ 17 อย่างแน่นอนขี้เกียจอ่านมาตรฐานทั้งหมด ;-) จะชี้แจงส่วนของขอบเขตไฟล์
Ciro Santilli 法轮功冠状病六四事件法轮功
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.