ใน C / C ++ ฉันควรใช้ 'const' ในพารามิเตอร์และตัวแปรท้องถิ่นเมื่อทำได้หรือไม่


14

คำถามนี้เป็นแรงบันดาลใจคำถามเกี่ยวกับfinalใน java

ใน C / C ++ ฉันควรใช้constทุกครั้งที่ทำได้หรือไม่

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

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

ดังนั้นฉันควรใช้constทุกครั้งที่ทำได้หรือไม่ ถ้าเป็นเช่นนั้นทำไมคำแนะนำสำหรับconstC ++ แตกต่างจากคำแนะนำสำหรับfinalใน Java

คำตอบ:


19

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

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

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


1
ขึ้นคะแนนเพราะคุณอธิบายว่าfinalและconstไม่มีการรับประกันเหมือนกัน
Bill Door

2
Constness นั้นเกี่ยวกับความสามารถในการเขียนไม่ใช่เรื่องความไม่แน่นอน
Basilevs

@Basilevs จะเกิดอะไรขึ้นหากคุณเขียนไปยังวัตถุ มันกลายพันธุ์ คุณจะกลายพันธุ์วัตถุได้อย่างไร เขียนถึงมัน

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

@Basilevs การสังเกตของคุณใช้กับการอ้างอิง const เท่านั้น ถ้าวัตถุนั้นถูกประกาศ const (ไม่ใช่แค่การอ้างอิง) มันจะไม่เปลี่ยนรูปได้มากขึ้นหรือน้อยลง
Matthew James Briggs

5

โดยส่วนตัวconstฉันใช้เวลาน้อยมากในการเขียนและเวลาในการอ่านน้อยมากมักจะน้อยกว่าที่ใช้ในการตรวจสอบว่าโค้ดใด ๆ กลายพันธุ์ตัวแปรหรือไม่และจริง ๆ แล้วมันป้องกันฉันจากการเขียนบั๊ก ฯลฯ )

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


4

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

ข้อดีของระดับบนสุดconstคือ:

  • ทำให้ชัดเจนว่าตัวแปรโลคัลไม่ได้หมายความว่าจะกลายพันธุ์
  • ให้ข้อผิดพลาดคอมไพเลอร์ถ้าคุณพยายามที่จะกลายพันธุ์พวกเขาโดยไม่ตั้งใจ

ข้อเสียคือ:

  • ภาพที่ยุ่งเหยิง
  • ไม่สามารถใช้กับตัวแปร "หลอกหลอก" ได้เช่นตัวแปรที่เริ่มต้นในบางลักษณะซับซ้อนกว่าการสร้างโดยตรง แต่ไม่ได้แก้ไขหลังจากใช้เช่นgetline:

    std::string line; // cannot be const
    std::getline(std::cin, line);
    // line should be const from here on out
  • ป้องกันการเพิ่มประสิทธิภาพการย้ายออกในการเรียกใช้ฟังก์ชันและส่งคืน:

    std::string f1();
    std::string f2(std::string s);
    std::string f3() {
      const std::string s = f1(); // s is not meant to be modified
      // but I still want the move optimization here:
      const std::string result = f2(std::move(s)); // this doesn't move
      // and I want the compiler to move out here:
      return result; // this will probably RVO, but if not, the move
                     // constructor will not be used due to the const
    }

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


2
จุดของคุณเกี่ยวกับการย้ายจากการแสดงที่คุณไม่ได้ใช้ในท้องถิ่นในลักษณะ const เป็นคุณ (ตั้งใจจะ) แก้ไขด้วยการย้าย
Caleth

1
@ Caleth ไม่นั่นคือประเด็น ฉันไม่ต้องการแก้ไข ฉันแค่ต้องการส่งผ่านค่าหรือส่งคืนและฉันต้องการให้มีประสิทธิภาพ แนวคิดการปรับเปลี่ยนเป็นเพียงการเพิ่มประสิทธิภาพซึ่งไม่ได้หมายถึงให้สามารถสังเกตได้ (เนื่องจากไม่ได้ใช้ตัวแปรหลังจากนั้น) ในทางปฏิบัติใช่มีการปรับเปลี่ยนเนื่องจาก C ++ ไม่มีการเคลื่อนไหวแบบทำลายล้างที่แท้จริง (เหมือนกับ Rust) นั่นเป็นสาเหตุที่ฉันไม่ต้องการconstคนในพื้นที่: เพราะมันช่วยป้องกันการดัดแปลงทางเทคนิคไม่ใช่แค่การปรับเปลี่ยนแนวคิด
เซบาสเตียนเรดล

2
คุณไม่ต้องการที่จะปรับเปลี่ยนค่าแต่คุณไม่ต้องการที่จะปรับเปลี่ยนตัวแปร คุณสามารถใช้ const & แทนและไม่สามารถแก้ไขได้
Caleth

2

constคำหลักที่ควรจะใช้สำหรับตัวแปรท้องถิ่นเช่นเดียวกับพารามิเตอร์ มันมีประโยชน์เพราะ:

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

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

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

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