C ++: การอ้างอิง const ก่อน vs หลังจากตัวระบุชนิด


144

อะไรคือข้อแตกต่างระหว่างข้อโต้แย้งใน:

int foo1(const Fred &arg) {
...
}

และ

int foo2(Fred const &arg) {
...
}

? ฉันไม่เห็นกรณีนี้ครอบคลุมในคำถามที่พบบ่อยของ parashift



2
นี่เป็นคำถามเกี่ยวกับสไตล์ไหม? "const Fred" ฟังดูดีในภาษาอังกฤษ แต่ "Fred const" ดูดีสำหรับฉัน
LatinSuD

1
ในหมายเหตุที่เกี่ยวข้องมีเหตุผลใดที่เราควรเลือกFred const &argมากกว่าFred const& arg? ฉันชอบอันหลังดีกว่าเพราะconst&เป็นหน่วยที่มีความหมายว่า "constref" และชื่อargจะถูกคั่นด้วยช่องว่างจากตัวระบุชนิดทั้งหมด
Frank

4
@dehmann: แต่int const& refไม่ได้หมายถึง 'const อ้างอิง' แต่ 'อ้างอิงถึง const'
Cedric H.

คำตอบ:


112

ไม่มีความแตกต่างเนื่องจาก const จะอ่านจากขวาไปซ้ายด้วยความเคารพ & ดังนั้นทั้งสองแสดงถึงการอ้างอิงถึงอินสแตนซ์ Fred ที่ไม่เปลี่ยนรูป

Fred& constจะหมายถึงการอ้างอิงตัวเองไม่เปลี่ยนรูปซึ่งซ้ำซ้อน ; เมื่อจัดการกับตัวชี้ constทั้งสอง Fred const*และFred* constถูกต้อง แต่แตกต่างกัน

มันเป็นเรื่องของสไตล์ แต่ผมชอบใช้constเป็นคำต่อท้ายเพราะมันสามารถนำมาใช้อย่างต่อเนื่องรวมถึงฟังก์ชั่นสมาชิก const


แล้วสิ่งที่เป็นจุดที่จะทำให้std::is_const<const T&>::valueเป็นfalse?
abyss.7

@ abyss.7 นั่นคือการอ้างอิงถึงconst T; การอ้างอิงนั้นไม่แน่นอน
Sean Fausett

125

พฤติกรรม

ไม่มีความแตกต่างทางความหมายระหว่างconst T&และT const&; ภาษาจะถือว่าเป็นประเภทเดียวกัน (สิ่งเดียวกันนี้ใช้กับconst T*และT const*.)

เป็นเรื่องของสไตล์

เกี่ยวกับเรื่องที่คุณควรชอบโวหาร แต่ฉันจะไม่เห็นด้วยกับคำตอบอื่น ๆ อีกมากมายและชอบconst T&(และconst T*):

  • const T&เป็นรูปแบบที่ใช้ในหนังสือภาษา C ++ Programming Stroustrup
  • const T& เป็นสไตล์ที่ใช้ในมาตรฐาน C ++ เอง
  • const T*เป็นสไตล์ที่ใช้ในหนังสือภาษา C Programmingของ K&R
  • const T* เป็นสไตล์ที่ใช้ในมาตรฐาน C
  • เนื่องจากปัจจัยดังกล่าวข้างต้นผมคิดว่าconst T&/ const T*มีความเฉื่อยวิธีที่มากกว่า/T const& / สังเกตุดูเหมือนจะเป็นเรื่องธรรมดาสำหรับฉันมากกว่า/ ในรหัส C ++ และ C ทั้งหมดที่ฉันเห็น ฉันคิดว่าการทำตามวิธีปฏิบัติทั่วไปสามารถอ่านได้มากกว่าการปฏิบัติตามกฎการแยกวิเคราะห์จากขวาไปซ้ายT const*const T&const T*T const&T const*
  • ด้วยT const*ดูเหมือนว่าจะวางผิดที่*เป็นT* const(โดยเฉพาะถ้าคนไม่คุ้นเคยกับมัน) ในทางตรงกันข้ามconst* Tไม่ใช่ไวยากรณ์ตามกฎหมาย

กฎการแยกวิเคราะห์จากขวาไปซ้ายมีอะไรบ้าง

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


3
+1 เห็นด้วย เมื่ออ่านรหัสมันจะง่ายต่อการตรวจจับ const หากบรรทัดขึ้นต้นด้วย const กฎซ้ายขวานั้นจำเป็นจริงๆเมื่อทำการแจงด้วยตนเองโดยเฉพาะการประกาศประเภทขน ทำไมไม่ปรับให้เหมาะสมสำหรับกรณีที่พบบ่อยที่สุด? นอกจากนี้ IMHO หากคุณเขียนการประกาศประเภทดังนั้นคุณต้องเรียกใช้ FSM ด้วยตนเองในหัวของคุณว่าคุณทำผิด
Andreas Magnusson

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

1
IMO เหตุผลที่const T&อ่านดีกว่าคือ: 1- เราอ่านโค้ดจากซ้ายไปขวา และ 2- เมื่ออธิบายแนวคิดใหม่ที่เราเริ่มต้นจากแนวคิดทั่วไปมากขึ้นเพื่อเฉพาะเจาะจงมากขึ้น ที่นี่constคำหลักกว้างกว่าเนื่องจากแบ่งพื้นที่ว่างเป็นสองประเภทในขณะที่ตัวระบุชนิดแบ่งส่วนออกเป็นหลาย ๆ
pooya13

"ตัวชี้ถึง" ควรอยู่ด้วยกัน ดังนั้นจึงไม่มีความกำกวมสำหรับT const*
Dexter

13

แม้ว่าพวกเขาจะเป็นหนึ่งเดียวกันเพื่อรักษาความสอดคล้องกับกฎRIGHT-LEFTเกี่ยวกับการแยกวิเคราะห์ประกาศ C และ C ++ มันจะดีกว่าที่จะเขียนFred const &arg

โปรดอ้างถึงสิ่งนี้สำหรับการพัฒนาความเข้าใจเพิ่มเติมเกี่ยวกับการประกาศผู้คัดเลือกและผู้ประกาศ


1
ฉันชอบคำต่อท้ายเพราะมันใช้งานได้ดีกับtypedefการขยายตัว ตัวอย่าง: typedef int* pointer;, const pointer ไม่ได้ ก็const int* int* constแบบฟอร์มต่อท้ายไม่ได้อึดอัด
Matthieu M.

4
IMO const T&จะอ่านจากขวาไปซ้ายด้วยเช่นกัน มันคือการอ้างอิงค่าคงที่ T Tและconstantแต่ละคนสามารถทำงานเป็นคำคุณศัพท์หรือคำนาม
jamesdlin

7

ทั้งงานและนี่คือคำอธิบายจากคนที่เขียนมัน
อ้างเขา:

ทำไม? เมื่อฉันคิดค้น "const" (ชื่อเดิมว่า "readonly" และมี "writeonly" ที่สอดคล้องกัน) ฉันอนุญาตให้มันไปก่อนหรือหลังประเภทเพราะฉันสามารถทำได้โดยไม่ต้องคลุมเครือ




3

การอ้างอิงไม่ทำงานในลักษณะเดียวกับพอยน์เตอร์: สำหรับพอยน์เตอร์คุณสามารถมี 'พอยน์เตอร์พอยน์' ( type * const p) และ 'พอยน์เตอร์ to const' ( const type * pหรือtype const * p)

แต่คุณไม่มีสิ่งนี้สำหรับการอ้างอิง: การอ้างอิงจะอ้างอิงถึงวัตถุเดียวกันเสมอ ในแง่นั้นคุณสามารถพิจารณาว่า 'การอ้างอิง' คือ 'การอ้างอิง const' (เช่นเดียวกับที่คุณมี 'ตัวชี้ const')

ดังนั้นบางอย่างเช่น 'ประเภทและการอ้างอิง const' จึงไม่ถูกกฎหมาย คุณสามารถมี 'อ้างอิงถึงประเภท' ( type &ref) และ 'อ้างอิงถึงประเภทคงที่' ( const type &refหรือtype const &ref ; ทั้งสองมีค่าเท่ากันทั้งหมด)

สิ่งสุดท้ายสิ่งหนึ่ง: แม้ว่าจะconst typeฟังดูถูกต้องมากขึ้นในภาษาอังกฤษการเขียนtype constจะช่วยให้เข้าใจคำประกาศอย่างเป็นระบบมากขึ้น "จากขวาไปซ้าย": int const & refสามารถอ่านได้ว่า 'อ้างอิงเป็นการอ้างอิงถึง int คงที่' หรือตัวอย่างที่ซับซ้อนมากขึ้น: int const * const & refการอ้างอิงเป็นการอ้างอิงไปยังตัวชี้ค่าคงที่ไปยังค่าคงที่

สรุป: ในคำถามของคุณทั้งสองมีความเท่าเทียมกันอย่างแน่นอน

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