ตัวชี้ที่ไม่ใช่ตัวเลือกเทียบกับการอ้างอิงที่ไม่ใช่แบบ const ใน C ++


12

ในคุณสมบัติ C ++ อื่น ๆ , อาร์กิวเมนต์อ้างอิงของคู่มือสไตล์ Google C ++ , ฉันอ่านว่าต้องไม่ใช้การอ้างอิงที่ไม่ใช่ const

พารามิเตอร์ทั้งหมดที่ส่งผ่านโดยการอ้างอิงจะต้องระบุว่า const

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

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

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


2
"การใช้พอยน์เตอร์ทำให้ตัวฟังก์ชันทั้งหมดถูกข้าม" เอ่ออะไรนะ?
วงล้อประหลาด

@ ratchetfreak ฉันพยายามชี้แจงเรื่องนี้ ฉันยอมรับว่าฟังก์ชันเช่นนี้อาจแสดงข้อบกพร่องในการออกแบบ ตัวชี้เป็นตัวเลือกที่เป็นทางการอยู่เสมอดังนั้นจึงต้องมีการตรวจสอบก่อนที่จะทำการอ้างอิงอีกครั้ง
Wolf

4
คู่มือสไตล์ C ++ ของ Google ค่อนข้างล้าหลัง ในความเห็นส่วนตัวของฉันมันควรจะถูกเผา
Siyuan Ren

สำหรับรายการนี้โดยเฉพาะฉันคิดว่าเหตุผลคือการบังคับให้โปรแกรมเมอร์เขียนเครื่องหมายและเมื่ออาร์กิวเมนต์อาจกลายพันธุ์แสดงเจตนาชัดเจนขึ้น
Siyuan Ren

4
Google Style Guide ถูกเขียนขึ้นเหมือนเดิมเพื่อสนับสนุนโค้ดที่เป็นเนื้อเดียวกันในโครงการดั้งเดิมของ Google หากคุณไม่ได้ทำงานในโครงการดั้งเดิม (ที่เขียนด้วยคู่มือสไตล์นี้ตั้งแต่ต้น) คุณอาจไม่ควรใช้มัน (มันระบุกฎมากมายที่ไม่ดีสำหรับรหัสใหม่ (c ++ 11, c ++ 14 , c ++ 17))
utnapistim

คำตอบ:


18

เหตุผลที่อยู่เบื้องหลังคู่มือสไตล์ของ Google ก็เพื่อทำให้ชัดเจนจากไซต์การเรียกใช้ของฟังก์ชันไม่ว่าพารามิเตอร์จะเป็นพารามิเตอร์อินพุตหรือพารามิเตอร์เอาต์พุต (ดูที่นี่สำหรับการสนทนาเพิ่มเติม) ภาษาอื่น ๆ สร้างพารามิเตอร์ที่ชัดเจนโดยการออกแบบ C #, ตัวอย่างเช่นมีoutหลักที่จะต้องใช้ในเว็บไซต์โทร เนื่องจาก C ++ ไม่ทำให้ชัดเจน Google จึงเลือกใช้การอ้างอิงแบบคงที่ เมื่อเทียบกับตัวชี้เพื่อให้ชัดเจน

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

โดยเฉพาะอย่างยิ่งแนวทางหลักของ C ++ Core ที่ประกาศใหม่นั้นต้องการค่าตอบแทนสำหรับพารามิเตอร์ขาออกสำหรับ (เกือบ) ทุกอย่างและใช้การอ้างอิงที่ไม่ใช่แบบคงที่สำหรับส่วนที่เหลือ การใช้พอยน์เตอร์กับการอ้างอิงของ Google อาจทำให้พารามิเตอร์เอาต์พุตชัดเจนขึ้น แต่ค่าส่งคืนจะชัดเจนขึ้น ตอนนี้ C ++ 11 มีการย้ายที่เป็นมาตรฐาน (การอ้างอิง rvalue &&, เพื่อให้ได้ผลตอบแทนหลายประเภทราคาถูก) และ tuples (ให้วิธีที่ง่ายในการคืนค่าหลายค่า), กรณีการใช้งานหลายพารามิเตอร์ไม่ได้ใช้อีกต่อไป

แนวทางหลัก C ++ มีชื่อใหญ่ ๆ (Bjarne Stroustrup, Herb Sutter) ที่อยู่ด้านหลังได้รับการสนับสนุนโดย Microsoft และยอมรับคุณลักษณะ C ++ ล่าสุด (ไม่เหมือนกับคู่มือสไตล์ของ Google) ดังนั้นฉันจึงคาดว่าคำแนะนำดังกล่าวจะได้รับความนิยมมากกว่า Google


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

ฉันไม่ได้ลืม แต่C ++ Core Guidelinesนั้นไม่ได้รับความรวดเร็วเท่านี้ เป็นที่น่าสนใจว่าปรัชญาแสดงเหตุผลที่อยู่เบื้องหลังกฎและมุมมองที่ทันสมัยเกี่ยวกับการเขียนโปรแกรม ("Express ideas โดยตรงใน code" อ่านนิดหน่อยเช่น Zen of python) เป็นวิธีการสื่อสาร
Wolf

ภาคผนวก: เชื่อมโยงโดยตรงไปยังส่วนปรัชญาของหลักเกณฑ์รหัส C ++
Wolf

1

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

การตรวจสอบทำได้ง่ายเพียง:

void foo(void* buffer){
    if(buffer == nullptr)
        return;

    //actually foo

    // note no increase in indentation required

}

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


ฉันคิดเกี่ยวกับรูปแบบนี้และพบว่ามันสมเหตุสมผลอย่างยิ่ง น่าเศร้าที่มันดูไม่ชัดเจนเท่าที่assert(buffer);ทราบว่าการยืนยันนั้นแอ็คทีฟสำหรับรุ่น debug บางครั้งฉันต้องการที่จะมีrt_assert(buffer);ข้อยกเว้น การเยื้องของreturnรูปลักษณ์นั้นอันตรายเล็กน้อย ... BTW: ข้อมูลโค้ดของคุณเป็นตัวอย่างที่ดีของคำถามเกี่ยวกับพอยน์เตอร์สำหรับเอาท์พุท
Wolf

1

If an output parameter is requiredมันลงมาให้การสังเกตของคุณ

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

ภายในคุณหลีกเลี่ยงพารามิเตอร์เอาท์พุทโดยการขยายประเภทผลตอบแทนให้เป็น "ส่วนเกิน" ทั้งหมด


คุณหมายถึงที่เดียวที่ฉันไม่สามารถให้ตัวชี้ที่ไม่บังคับได้? จริง แต่ฉันไม่แน่ใจว่ากฎของคุณThe only place where...ใช้ได้กับทุกกรณีหรือไม่ สิ่งที่คุณแนะนำมีลักษณะดังนี้: หลีกเลี่ยงพารามิเตอร์เอาต์พุตในฟังก์ชันของโปรแกรมของคุณเอง เป็นจริงสำหรับโปรแกรมใหม่
Wolf

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