คุณเปลี่ยนความถูกต้องของ const ได้อย่างไร? [ปิด]


25

หลังจาก 15 ปีของ C ++ ฉันยังไม่ได้เรียนรู้ที่จะรักโดยใช้ const ฉันเข้าใจว่ามันใช้งานได้ แต่ฉันไม่เคยอยู่ในสถานการณ์ที่ถูกต้อง constจะหลีกเลี่ยงปัญหาที่ฉันเผชิญ

แล้วคุณมารักผลประโยชน์ของกลุ่มดาวได้อย่างไร?


3
ฉันคิดว่าความถูกต้องของ const นั้นถูกต้องมากกว่าเครื่องมือในการแก้ปัญหาเช่นถ้า constrcut หรือตัวดำเนินการ sizeof
ตำนาน 2k

9
"เหตุผลที่ const ทำงานใน C ++ นั้นเป็นเพราะคุณสามารถทิ้งมันไปได้ถ้าคุณไม่สามารถทิ้งมันไปได้โลกของคุณก็จะดูด" - Anders Hejlsberg
Mason Wheeler

1
const ยังเป็นตัวแก้ไขประเภท C และได้รับตั้งแต่มาตรฐาน ANSI C แรก
Huperniketes

ถูกทำลายโดย Java / C # ฉันเป็นคนหวาดระแวงที่ชอบออกความเห็นในโอกาสใดก็ตามที่ฉันได้รับ สิ่งที่ผิดพลาดได้จะผิดไป หากมีการรวบรวมเวลาหรือความช่วยเหลือเวลาทำงานแล้วนับฉันด้วย! ฉันกลายเป็นผู้เปลี่ยนใจเลื่อมใสทันทีที่ฉันได้ยินเกี่ยวกับมัน 3-4 ครั้งและติดตามส่วนหนึ่งของลิงค์นี้ (พอที่จะดูไวยากรณ์ฉันไม่จำเป็นต้องอ่านเกี่ยวกับสาเหตุ): ความเป็นไปได้ / Cpp/const.htmlเพียงเพราะบางสิ่งบางอย่างไม่ได้ปลิวไปที่ใบหน้าของฉัน ... มันต้องใช้ความพยายามเล็กน้อยในการแก้ไขให้ถูกต้องและไม่เจ็บ ตรวจสอบความคิดของ Joel: joelonsoftware.com/articles/Wrong.html
งาน

คำตอบ:


28

ฉันไม่มั่นใจจนกระทั่งฉันพยายามยอมรับปรัชญา

ฉันเริ่มแรกด้วยการทำให้constสมาชิกแบบอ่านอย่างเดียวของสมาชิกคลาสพื้นฐานที่สุดของฉันและการโต้แย้งฟังก์ชันสมาชิก

จากตรงนั้นฉันไม่สามารถรวบรวมได้อีก จากนั้นฉันก็พยายามที่จะใช้รหัสโดยใช้คลาสพื้นฐานเหล่านั้นดูว่าการconstเพิ่มก่อนหน้านี้นั้นถูกต้องตามกฎหมายหรือไม่เมื่อเทียบกับการใช้ที่ฉันทำ มันช่วยให้ฉันแก้ไขข้อบกพร่องบางอย่างในขณะที่ฉันเพิ่มความมั่นคงให้กับส่วนอื่น ๆ ของรหัส

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

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

ฉันมั่นใจ

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


8
+1 สำหรับการติดต่อซึ่งหมายความว่าคุณต้องแปลง const หรือหลีกเลี่ยงโดยสิ้นเชิง
Martin Wickman

คุณต้องไม่พึ่งพา libs ที่ไม่ได้แก้ไขความถูกต้อง const วิธีการของคุณไม่ทำงานเมื่อมันหมายความว่าคุณไม่สามารถเรียกฟังก์ชัน gui ใด ๆ ได้เพราะมันไม่ได้เป็น const - หรือคุณจำเป็นต้องใช้มันในทุก ๆ การเรียก gui
Martin Beckett

4
+1 สำหรับ "พบว่าง่ายต่อการดีบัก" ฉันใช้constแม้กระทั่งตัวแปรท้องถิ่นที่ฉันรู้ว่าฉันไม่จำเป็นต้องเปลี่ยนวิธีนี้เมื่ออ่านโค้ดฉันสามารถอ่านผ่านifหรือ a forหรือ whatelse: ตัวแปรของฉันเป็นค่าคงที่ฉันรู้ว่ามันจะไม่เปลี่ยนแปลง! ฉันไม่สนใจการเพิ่มประสิทธิภาพ แต่ฉันมีสมองที่ จำกัด และการเยื้องระดับ + การแก้ไขความผิดพลาดอย่างมากช่วยให้ฉันลดน้อยลงอย่างมาก!
Matthieu M.

@MatthieuM: เคยเปลี่ยนมาใช้ Haskell ไหม? ;-)
Giorgio

@Giorgio: ฉันได้สำรวจมันแล้วแม้กระทั่งการซื้อ "Real World Haskell" ความซื่อสัตย์ฉันไม่ได้ตื่นเต้นกับความเกียจคร้านโดยปริยายและผู้ให้บริการที่ซ่อนเร้นหลายคนที่ผุดขึ้นมา
Matthieu M.

15

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

โดยพื้นฐานแล้วทุกอย่างที่ไม่เปลี่ยนรูปอาจจะเป็นอย่างนั้นเว้นแต่คุณจะมีเหตุผลที่ดีสำหรับการเปลี่ยนแปลงสถานะ จากประสบการณ์ของฉันการเขียนโปรแกรมในภาษาใด ๆเพื่อให้บรรลุเป้าหมายนี้นำไปสู่รหัสที่ปลอดภัยและดีกว่า คุณไม่มีอะไรจะเสียโดยการใช้constที่เหมาะสม - ความไม่สามารถเปลี่ยนแปลงได้ฟรี!

(อนึ่งฉันได้ลองคิดกับการสร้างทางแยกของ GCC สำหรับภาษา C ++ ซึ่งทุกประเภทconstยกเว้นว่ามีคุณสมบัติชัดเจนmutableหากมีการสนับสนุนสิ่งดังกล่าวฉันจะมุ่งมั่นที่จะรักษาและใช้งาน)


จากมุมมองของ OO ความไม่สามารถเปลี่ยนแปลงได้นั้นบังคับใช้การห่อหุ้มโดยป้องกันการเข้าถึงการเขียนที่ไม่ จำกัด มันลดการมีเพศสัมพันธ์ระหว่างชั้นเรียนเพราะวัตถุที่ไม่เปลี่ยนรูปจะต้องจัดการสถานะของตนเองอย่างสมบูรณ์และจึงทำตัวเหมือนค่าปกติ ความถูกต้อง Const ช่วยลดขั้นตอนการพิสูจน์ความถูกต้องของโปรแกรมโดยเฉพาะอย่างยิ่งในบริบทของการเขียนโปรแกรมพร้อมกัน ด้วยการอ้างอิง C ++ และซีแมนทิกส์การอ้างอิง rvalue C ++ 0x คุณสามารถใช้ประโยชน์จากวัตถุที่ไม่เปลี่ยนรูปได้โดยไม่ต้องกังวลเกี่ยวกับค่าใช้จ่ายในการคัดลอกพวกเขาไปทั่วสถานที่ นอกจากนี้คอมไพเลอร์ยังสามารถใช้เวทย์มนตร์เพิ่มประสิทธิภาพที่น่าทึ่งได้หากคุณทำงานกับวัตถุที่ไม่เปลี่ยนรูปแบบส่วนใหญ่

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


2
คุณเพียงแค่บอกว่าความถูกต้อง const เป็นสิ่งที่ดี คุณบอกว่ามัน "นำไปสู่ความปลอดภัยรหัสที่ดีกว่า" คุณพูดทำไม
David Reis

ฉันอยู่ในค่ายที่ไม่สามารถเปลี่ยนแปลงได้ภาษาที่ฉันชอบคือ Erlang แต่ฉันจะยืนยันว่าการเปลี่ยนไม่ได้ผ่าน const ใน C ++ นั้นไม่ฟรีจริงๆ มีข้อเสียเช่นรหัสที่อ่านได้น้อยลงรุ่น const และไม่ใช่ const ของวิธีการเดียวกันหรือการคัดทิ้งไปทำให้เกิดสาเหตุ "ไม่มีทางเลือกอื่น"
grok

1
ฉันแนะนำไม่เพียง แต่ใช้mutableเพราะมันมีความหมายที่ชัดเจนในแง่ของความถูกต้อง const หมายความว่าวัตถุข้อมูลนี้สามารถเปลี่ยนแปลงได้ในลักษณะที่ไม่ส่งผลกระทบต่อพฤติกรรมวัตถุและอนุญาตให้ใช้สิ่งต่าง ๆ เช่นคำตอบแคช สร้างคำค้นหาอื่น
David Thornley

2
@ David Thornley: เพื่อประโยชน์ของความมั่นคงmutableเป็นตัวเลือกที่สมเหตุสมผล void alter(mutable Point&)ทำให้ความรู้สึกเช่นเดียวกับการหาตัวแปรท้องถิ่นและค่าของความขัดแย้งเหล่านี้ด้วยภาษาที่มีอยู่หรือการใช้งานที่มีอยู่ของmutable int foo mutableนอกจากนี้Object mutable* mutableดูน่ากลัวพอที่จะเตือนว่าจำเป็นหรือถูกต้อง
Jon Purdy

หากคุณเคยแยกลองพิจารณาใช้ CLang แทน - ควรเจ็บปวดน้อยกว่า
gf

6

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

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


1
"โปรแกรมจะต้องถูกเขียนขึ้นเพื่อให้ผู้คนอ่านและมีเพียงเครื่องเท่านั้นที่จะทำงาน" - Abelson & Sussman,
SICP

4

ความถูกต้องconstเน้นความถูกต้องของการออกแบบที่ฉันปฏิบัติใกล้เคียงกับปัญหาที่คล้ายกันซึ่งไม่ได้ใช้ตัวดำเนินการ cast ดังนั้นอย่าใช้การ cast และการแก้ไขให้ถูกต้องการใช้งาน mutable น้อยที่สุด - ทั้งหมดนี้เป็นตัวชี้วัดการออกแบบที่ดีแต่ไม่ใช่เครื่องมือจริงในการแก้ปัญหาโดยรวมในมือ

PS:ฉันมั่นใจโดยสิ้นเชิงconstเมื่อฉันเข้าใจความถูกต้องในการใช้มัน)



2

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


2

ฉันเป็นผู้เปลี่ยนใจเลื่อมใสทันทีที่ฉันรู้ว่ามันเป็นไปได้ มันสมเหตุสมผลสำหรับฉันจากจุดยืน 'รูปแบบการเขียนโปรแกรมที่ดี' มีหลายเหตุผลว่าทำไมจึงเป็นวิธีปฏิบัติที่ดีในการแก้ไข const:

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

2

เพื่อสรุปสองจุดที่ครอบคลุมในคำตอบอื่น ๆ และเพิ่มจุดใหม่:

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

  • constจัดทำเอกสารแสดงเจตนาของคุณต่อคอมไพเลอร์ การค้นหาข้อผิดพลาดในเวลารวบรวมนั้นดีกว่าการรอให้โค้ดนั้นรัน

  • constจำเป็นสำหรับ polymorphism ชนิดปลอดภัย พอยน์เตอร์ (ในทุกรูปแบบไม่ใช่แค่พอยน์เตอร์พ้อยท์) เป็นเพียง covariant หากเป็นconst(หมายเหตุ: ไม่เหมือนกับ "ตัวชี้ไปยัง const") ความแปรปรวนร่วมต้องการอินเทอร์เฟซแบบอ่านอย่างเดียวและความแปรปรวนร่วมต้องการอินเทอร์เฟซแบบเขียนอย่างเดียว

ครั้งที่สองของสิ่งเหล่านี้ฉันได้เรียนรู้ก่อน ฉันเริ่มต้นด้วยconstเป้าหมายของตัวชี้และพารามิเตอร์อ้างอิงจนกระทั่งฉันเริ่มเห็นประโยชน์ของการจับข้อผิดพลาดก่อนหน้านี้และเริ่มใช้กับคนในท้องถิ่น ฯลฯ

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

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


1

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

มันเป็นหลักการเดียวกัน แต่ฉันแค่ต้องการเพิ่มเหตุผลที่ใช้งานได้จริงของการใช้ const

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