การเลิกใช้งานคำหลักคงที่ ... ไม่มีอีกแล้วหรือ


89

ใน C ++ เป็นไปได้ที่จะใช้staticคีย์เวิร์ดภายในหน่วยการแปลเพื่อส่งผลต่อการแสดงสัญลักษณ์ (ไม่ว่าจะเป็นการประกาศตัวแปรหรือฟังก์ชัน)

ใน n3092 สิ่งนี้เลิกใช้แล้ว:

ภาคผนวก D.2 [depr.static]
การใช้คีย์เวิร์ดแบบคงที่จะเลิกใช้เมื่อประกาศอ็อบเจ็กต์ในขอบเขตเนมสเปซ (ดู 3.3.6)

ใน n3225 สิ่งนี้ถูกลบออก

บทความเดียวที่ฉันจะหาค่อนข้างเป็นทางการ

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

มีใครรู้บ้างว่าทำไมถึงเปลี่ยน?


3
คุณประกาศวัตถุที่ขอบเขตเนมสเปซใน C?
Etienne de Martel

เฮ้ขอบคุณพบว่าจะจับมันได้ที่ไหน พยายามลบความคิดเห็น แต่คุณเอาชนะฉันที่นั่น
Edward Strange

คำถามเกิดจากstackoverflow.com/questions/4725204/…
Fred Nurk

1
นอกจากนี้ยังเปิดโอกาสให้คณะกรรมการ C ++ ยกเลิกการหาข้อมูลบางอย่างใน Standard รุ่นถัดไป :-)
James McNellis

คำตอบ:


75

ในรายงานข้อบกพร่องของภาษาหลักมาตรฐาน C ++ และปัญหาที่ยอมรับให้แก้ไข 94ภายใต้1012 เลิกใช้งานแบบคงที่ `พวกเขาทราบว่า:

แม้ว่า 7.3.1.1 [namespace.unnamed] จะระบุว่าการใช้คีย์เวิร์ดแบบคงที่สำหรับการประกาศตัวแปรในขอบเขตเนมสเปซนั้นเลิกใช้แล้วเนื่องจากเนมสเปซที่ไม่มีชื่อเป็นทางเลือกที่ดีกว่า แต่ก็ไม่น่าจะมีการนำฟีเจอร์นี้ออกไปในอนาคตอันใกล้ .

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


2
ดูเหมือนว่าการเลิกใช้งานจะกระตุ้นให้ผู้คนใช้เนมสเปซที่ไม่มีชื่อแทนซึ่งจะเป็นสิ่งที่ดี
sbi

1
@unaperson: หากไม่มีเหตุผลอื่นเนื่องจากเนมสเปซที่ไม่มีชื่อมีกลไกเดียวกันในการสร้างตัวแปรค่าคงที่ฟังก์ชันและประเภทภายในของ TU static class ... OTOH ไม่ทำงาน
sbi

2
@nbt: เนื่องจากคุณไม่สามารถใช้สัญลักษณ์แบบคงที่เป็นอาร์กิวเมนต์ของเทมเพลตได้และเนื่องจากมือใหม่หลาย ๆ คนพบว่าคงใช้งานได้ง่ายกว่าดังนั้นจึงไม่ได้รับการพยายามลองใช้ <functional> และ <algorithm> et al เพียงแค่คิดอย่างรวดเร็ว
Sebastian Mach

3
"เพราะคุณไม่ต้องการรหัสสำเร็จรูปที่คุณต้องการกับเนมสเปซที่ไม่มีชื่อ"? "รหัสสำเร็จรูป" คืออะไร สิ่งที่อยู่นอกเหนือจาก " namespace {" และ " }"?
towi

2
@ErikAronesty หากคุณมี "คลาสโลคัล" ในไฟล์อื่นที่มีชื่อเดียวกันคุณจะละเมิด ODR
LF

32

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

ใน C ++ เป็นไปได้ที่จะใช้คีย์เวิร์ดแบบคงที่ภายในหน่วยการแปลเพื่อส่งผลต่อการแสดงสัญลักษณ์ (ตัวแปรหรือการประกาศฟังก์ชัน)

การเชื่อมโยงจริง

ใน n3092 สิ่งนี้เลิกใช้แล้ว:

การเลิกใช้งานบ่งชี้:

  • ความตั้งใจที่จะลบคุณลักษณะบางอย่างในอนาคต นี่ไม่ได้หมายความว่าคุณลักษณะที่เลิกใช้แล้วจะถูกลบออกในการแก้ไขมาตรฐานครั้งต่อไปหรือจะต้องถูกลบออก "ในไม่ช้า" หรือเลย และคุณลักษณะที่ไม่เลิกใช้งานอาจถูกลบออกในการแก้ไขมาตรฐานครั้งถัดไป
  • ความพยายามอย่างเป็นทางการเพื่อกีดกันการใช้งาน

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

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

เป็นสิ่งสำคัญมากในการเก็บรักษาชุดย่อยทั่วไปของ C / C ++ โดยเฉพาะอย่างยิ่งสำหรับไฟล์ส่วนหัว แน่นอนว่าstaticการประกาศทั่วโลกเป็นการประกาศสัญลักษณ์ที่มีการเชื่อมโยงภายในและสิ่งนี้ไม่มีประโยชน์มากนักในไฟล์ส่วนหัว

แต่ปัญหาไม่ได้เป็นเพียงความเข้ากันได้กับ C เท่านั้น แต่ยังเข้ากันได้กับ C ++ ที่มีอยู่: มีโปรแกรม C ++ ที่ถูกต้องมากมายที่ใช้staticการประกาศส่วนกลาง รหัสนี้ไม่ได้เป็นเพียงทางกฎหมายอย่างเป็นทางการก็คือเสียงดังที่จะใช้ภาษาคุณลักษณะที่ดีที่กำหนดวิธีการที่มันมีจุดมุ่งหมายที่จะใช้

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

ในทำนองเดียวกันฉันจะไม่เปลี่ยนรูปแบบ C doubleเป็นstatic_cast<double>เพียงเพราะ "การร่ายแบบ C ไม่ดี" เนื่องจากstatic_cast<double>จะเพิ่มข้อมูลเป็นศูนย์และไม่มีความปลอดภัย

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

การเปลี่ยนแปลงโค้ดจำเป็นต้องมีเหตุผลและ "เก่าไม่ดี" ไม่ใช่เหตุผลสำหรับการเปลี่ยนแปลงโค้ด

การเปลี่ยนแปลงภาษาที่ไม่เหมาะสมจำเป็นต้องมีเหตุผลที่ชัดเจนมาก การทำให้ภาษาง่ายขึ้นเล็กน้อยไม่เคยเป็นเหตุผลสำหรับการเปลี่ยนแปลงที่รุนแรง

เหตุผลที่ระบุว่าทำไมถึงstaticไม่ดีจึงอ่อนแออย่างน่าทึ่งและยังไม่ชัดเจนว่าทำไมจึงไม่เลิกใช้ทั้งวัตถุและการประกาศฟังก์ชันด้วยกันการให้การรักษาที่แตกต่างกันแทบจะไม่ทำให้ C ++ ง่ายขึ้นหรือตั้งฉากกันมากขึ้น

ดังนั้นมันจึงเป็นเรื่องที่น่าเศร้า ไม่ใช่เพราะผลในทางปฏิบัติมันไม่มีผลในทางปฏิบัติอย่างแน่นอน แต่เนื่องจากแสดงให้เห็นถึงการขาดสามัญสำนึกอย่างชัดเจนจากคณะกรรมการ ISO.


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

2
ฉันไม่สนใจมากนักเกี่ยวกับผู้คนที่ใช้ขอบเขตทั่วโลกstaticหรือเนมสเปซที่ไม่ระบุตัวตนฉันไม่ได้ให้กำลังใจหรือท้อใจเช่นกัน ประเด็นของฉันคือถ้าคุณต้องการกีดกันผู้คนให้ใช้เนมสเปซที่ไม่ระบุตัวตนคุณต้องให้เหตุผลที่ดีแก่พวกเขา ในทางปฏิบัติฉันเชื่อว่าในเอนทิตีการนำไปใช้งานส่วนใหญ่ที่ประกาศในเนมสเปซที่ไม่มีชื่อเป็นสัญลักษณ์ที่ส่งออกด้วยชื่อแบบสุ่มดังนั้นตารางการส่งออกจะเพิ่มขึ้น เอนทิตีที่ประกาศเป็นstaticOTOH จะไม่ถูกส่งออก แต่อย่างใด ดังนั้นผู้คนจำนวนมากจึงเลือกใช้ตามข้อสังเกตstaticนั้น
ซอกแซก

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

5
ภาษาทั้งหมดจะ "หายไปในบางวัน" เลิกใช้งาน C ++ กันเถอะ
Lightness Races ในวงโคจร

2
"ในรูปแบบที่คล้ายกันฉันจะไม่เปลี่ยนแคสต์สไตล์ C เป็นสองเท่าเป็น static_cast <double> เพียงเพราะ" แคสต์แบบ C ไม่ดี "เนื่องจาก static_cast <double> เพิ่มข้อมูลเป็นศูนย์และไม่มีความปลอดภัย" การต่อสู้ชั่วนิรันดร์ของฉันกับวิศวกรซอฟต์แวร์หลายคนที่เอาแต่บ่นเกี่ยวกับการใช้รูปแบบ C แบบเสรีของฉันตั้งแต่ดั้งเดิมไปจนถึงอีกแบบหนึ่ง
Makogan

14

เลิกใช้หรือไม่การลบคุณลักษณะภาษานี้จะทำลายรหัสที่มีอยู่และรบกวนผู้อื่น

การเลิกใช้งานแบบคงที่ทั้งหมดเป็นเพียงความคิดที่ปรารถนาตามแนวของ "เนมสเปซที่ไม่ระบุตัวตนดีกว่าคงที่" และ "การอ้างอิงเป็นตัวชี้ที่ดีกว่า" ฮ่า ๆ.


1
"การอ้างอิงเป็นตัวชี้ที่ดีกว่า"? ไม่พอยน์เตอร์อัจฉริยะเป็นตัวชี้ที่ชาญฉลาดกว่า คุณไม่สามารถใช้การอ้างอิงสำหรับหน่วยความจำที่จัดสรรจาก heap, err, free store
Dan Breslau

3
ขอโทษค่ะลืมปิดท้ายด้วยสไมลี่แดกดัน
Maxim Egorushkin

2
@ แดน: นั่นคือสิ่งที่คำตอบนี้บอกว่า: "ความคิดที่ปรารถนา" ตามแนวความคิดที่ผิดพลาดคล้าย ๆ กัน เนมสเปซที่ไม่มีชื่อเป็นคุณลักษณะที่สำคัญเช่นเดียวกับ global-scope-static แม้ว่าจะมีเหตุผลที่แตกต่างกันเล็กน้อยและแม้ว่าจะมีการใช้งานที่ทับซ้อนกันอยู่บ้างก็ตาม
Fred Nurk

@ เฟรด @ แม็กซิม: ขออภัยหากฉันเข้าใจผิดหรือหากความจำของฉันผิดพลาด แต่ฉันไม่ได้จัดหมวดหมู่ "การอ้างอิงเป็นตัวชี้ที่ดีกว่า" เนื่องจากเทียบเท่ากับ "เนมสเปซที่ไม่ระบุตัวตนดีกว่าคงที่" ในกรณีของความคิดที่ปรารถนา ฉันตระหนักดีถึงความพยายามในการทำสิ่งหลัง แต่ฉันจำไม่ได้ว่ามีใครยื่นข้อเสนอจริงจังเพื่อแทนที่คำแนะนำด้วยการอ้างอิง อีกครั้งอาจจะเป็นความตระหนักรู้ของฉันเองที่ขาดไป
Dan Breslau

1
@ DanBreslau: char* foo = new char; char& ref = *foo;เพียงเพราะคุณได้รับตัวชี้ในตอนแรกบอกว่าไม่มีอะไรเกี่ยวกับความสามารถในการใช้การอ้างอิง
Lightness Races ใน Orbit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.