ฉันควรเลือกพอยน์เตอร์หรือการอ้างอิงในข้อมูลสมาชิกหรือไม่?


138

นี่เป็นตัวอย่างง่าย ๆ เพื่อแสดงคำถาม:

class A {};

class B
{
    B(A& a) : a(a) {}
    A& a;
};

class C
{
    C() : b(a) {} 
    A a;
    B b; 
};

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

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

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

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


"แต่การคัดลอกและการมอบหมายเริ่มต้นก็ไม่ดีกับพอยน์เตอร์": สิ่งนี้ไม่เหมือนกัน: ตัวชี้สามารถเปลี่ยนแปลงได้ทุกเมื่อที่คุณต้องการหากไม่ใช่ const การอ้างอิงปกติมักจะเป็น const! (คุณจะเห็นสิ่งนี้หากคุณพยายามเปลี่ยนสมาชิกของคุณเป็น "A & const a;" คอมไพเลอร์ (อย่างน้อย GCC) จะเตือนคุณว่าการอ้างอิงนั้นยังคงเป็น const อยู่แม้ว่าจะไม่มีคำหลัก "const" ก็ตาม
mmmmmmmm

ปัญหาหลักของเรื่องนี้คือถ้าใครบางคนทำ B b (A ()) คุณจะเมาเพราะคุณจะจบลงด้วยการอ้างอิงห้อยต่องแต่ง
บันทึก 0

คำตอบ:


67

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

ตัวอย่างปัญหา:

  • คุณถูกบังคับให้เริ่มต้นการอ้างอิงในรายการตัวกำหนดค่าเริ่มต้นของตัวสร้างแต่ละตัว: ไม่มีวิธีแยกตัวประกอบการเริ่มต้นนี้ไปยังฟังก์ชันอื่น ( จนกระทั่ง C ++ 0x, แก้ไขต่อไป: C ++ ตอนนี้มีการมอบหมาย Constructor )
  • การอ้างอิงไม่สามารถฟื้นตัวหรือเป็นโมฆะ นี่อาจเป็นข้อได้เปรียบ แต่ถ้ารหัสจำเป็นต้องเปลี่ยนเพื่ออนุญาตให้ rebinding หรือสมาชิกเป็นโมฆะการใช้ทั้งหมดของสมาชิกจำเป็นต้องเปลี่ยน
  • ไม่เหมือนกับสมาชิกตัวชี้การอ้างอิงไม่สามารถถูกแทนที่ได้อย่างง่ายดายด้วยตัวชี้สมาร์ทหรือตัววนซ้ำเนื่องจากการปรับโครงสร้างอาจต้องใช้
  • เมื่อใดก็ตามที่มีการใช้การอ้างอิงจะดูเหมือนว่าประเภทของค่า ( .โอเปอเรเตอร์และอื่น ๆ ) แต่จะทำงานเหมือนตัวชี้ (สามารถห้อย) - ดังนั้นเช่นGoogle Style Guideไม่สนับสนุน

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

4
@ Mykola: ฉันเห็นด้วยกับคุณ ฉันต้องการให้สมาชิกเริ่มต้นในรายการผู้เริ่มต้นฉันหลีกเลี่ยงพอยน์เตอร์พอยน์เตอร์และแน่นอนว่าไม่ดีสำหรับตัวแปรที่จะเปลี่ยนความหมายของมัน ความคิดเห็นของเราต่างกันตรงที่ฉันไม่ต้องการหรือต้องการให้คอมไพเลอร์บังคับใช้สิ่งนี้สำหรับฉัน มันไม่ได้ทำให้การเรียนง่ายขึ้นฉันไม่ได้เจอข้อบกพร่องในพื้นที่นี้ที่มันจะจับได้และบางครั้งฉันก็ชื่นชมความยืดหยุ่นที่ฉันได้รับจากรหัสที่ใช้สมาชิกตัวชี้อย่างสม่ำเสมอ (ตัวชี้สมาร์ทที่เหมาะสม)
James Hopkin

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

4
James ไม่ใช่ว่ามันจะทำให้รหัสง่ายขึ้นในการเขียนมันทำให้โค้ดอ่านง่ายขึ้น ด้วยการอ้างอิงในฐานะสมาชิกข้อมูลคุณไม่ต้องสงสัยว่ามันจะเป็นโมฆะ ณ จุดใช้งานหรือไม่ ซึ่งหมายความว่าคุณสามารถดูรหัสโดยใช้บริบทน้อยลง
Len Holgate

4
มันทำให้การทดสอบหน่วยและการเยาะเย้ยมากขึ้นเป็นไปไม่ได้เกือบขึ้นอยู่กับจำนวนที่ใช้รวมกับ 'ส่งผลกระทบต่อการระเบิดกราฟ' เป็น IMHO ที่น่าสนใจด้วยเหตุผลเพียงพอที่จะไม่ใช้พวกเขา
Chris Huang-Leaver

156

กฎง่ายๆของฉัน:

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

1
ฉันคิดว่าของคุณและ Mykola เป็นคำตอบที่ถูกต้องและส่งเสริมการเขียนโปรแกรม pointerless (อ่านน้อยกว่าตัวชี้)
amit

37

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

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

และอาจเป็นการดีที่จะอธิบายความสัมพันธ์แบบหนึ่งหรือศูนย์เป็นตัวชี้

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

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


2
+1: เหมือนกันฉันมีประสบการณ์ มีคลาสหน่วยเก็บข้อมูลทั่วไปบางคลาสเท่านั้นที่ต้องการ assignemtn และ copy-c'tor และสำหรับกรอบวัตถุทางธุรกิจระดับสูงเพิ่มเติมควรมีเทคนิคอื่น ๆ สำหรับการคัดลอกที่จัดการกับสิ่งต่างๆเช่น "อย่าคัดลอกเขตข้อมูลที่ไม่ซ้ำ" และ "เพิ่มไปยังผู้ปกครองคนอื่น" เป็นต้นดังนั้นคุณจึงใช้กรอบงานระดับสูงเพื่อคัดลอกวัตถุธุรกิจของคุณ และไม่อนุญาตการมอบหมายระดับต่ำ
mmmmmmmm

2
+1: ข้อตกลงบางข้อ: สมาชิกอ้างอิงที่ป้องกันผู้ปฏิบัติงานที่ได้รับมอบหมายนั้นไม่ได้เป็นข้อโต้แย้งที่สำคัญ ในขณะที่คุณระบุอย่างถูกต้องในลักษณะที่แตกต่างกันวัตถุบางอย่างเท่านั้นที่มีความหมายของค่า ฉันยอมรับด้วยว่าเราไม่ต้องการ 'ถ้า (p)' กระจัดกระจายไปทั่วโค้ดโดยไม่มีเหตุผล แต่วิธีการที่ถูกต้องคือผ่านค่าคงที่ของคลาส: คลาสที่กำหนดไว้อย่างดีจะไม่มีที่ว่างสำหรับข้อสงสัยว่าสมาชิกสามารถเป็นโมฆะได้หรือไม่ หากตัวชี้ใด ๆ สามารถเป็นโมฆะในรหัสฉันคาดหวังว่าจะแสดงความคิดเห็นได้ดี
James Hopkin

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

11

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

ใช่ฉันไม่คิดว่านี่เป็นคำแนะนำที่ดีในบริบทของการอ้างอิงของสมาชิก
ทิมแองกัส

6

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

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

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


6

ในขณะที่ทุกคนดูเหมือนจะแจกกฎทั่วไปฉันจะเสนอให้สองข้อ:

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

  • ใช้การอ้างอิงเสมอเมื่อส่งพารามิเตอร์ไปยังฟังก์ชันยกเว้นประเภทพื้นฐานหรือเมื่ออัลกอริทึมต้องการสำเนา

กฎเหล่านี้เรียบง่ายและทำให้ฉันอยู่ในตำแหน่งที่ดี ฉันปล่อยให้กฎในการใช้ตัวชี้สมาร์ท (แต่โปรดไม่ใช่ auto_ptr) ในฐานะสมาชิกชั้นเรียนให้กับผู้อื่น


2
ไม่เห็นด้วยกับคนแรก แต่ความขัดแย้งไม่ได้เป็นปัญหาในการให้เหตุผล +1
David Rodríguez - dribeas

(ดูเหมือนว่าเราจะสูญเสียเรื่องนี้กับผู้มีสิทธิเลือกตั้งที่ดีของ SO แม้ว่า)
เจมส์ Hopkin

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

1
นีล> ฉันเห็นด้วย แต่มันไม่ใช่ "ความเห็น" ที่ทำให้ฉันลงคะแนนมันเป็นการยืนยันที่ "ไม่เคย" การโต้เถียงที่นี่ดูเหมือนจะไม่เป็นประโยชน์ต่อไปฉันจะยกเลิกการลงคะแนนของฉัน
Klaim

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

4

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

กฎง่ายๆสำหรับสมาชิกข้อมูล:

  • อย่าใช้การอ้างอิงเพราะเป็นการป้องกันการมอบหมาย
  • ถ้าคลาสของคุณรับผิดชอบการลบให้ใช้ boost ของ scoped_ptr (ซึ่งปลอดภัยกว่า auto_ptr)
  • มิฉะนั้นให้ใช้ตัวชี้หรือตัวชี้ const

2
ฉันไม่สามารถตั้งชื่อเคสได้เมื่อฉันต้องการกำหนดวัตถุธุรกิจ
Mykola Golubyev

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

auto_ptr ป้องกันการมอบหมาย (เหมาะสม) ด้วย

2
@ Mykola: ฉันยังได้รับประสบการณ์ที่ 98% ของวัตถุธุรกิจของฉันไม่จำเป็นต้องได้รับมอบหมายหรือคัดลอก c'tors ฉันป้องกันสิ่งนี้ด้วยแมโครขนาดเล็กที่ฉันเพิ่มไว้ในส่วนหัวของคลาสเหล่านั้นซึ่งทำให้คัดลอก c'tors และ operator = () ส่วนตัวโดยไม่มีการใช้งาน ดังนั้นใน 98% ของวัตถุฉันจึงใช้การอ้างอิงและมันก็ปลอดภัย
mmmmmmmm

1
การอ้างอิงในฐานะสมาชิกสามารถใช้เพื่อระบุอย่างชัดเจนว่าชีวิตของอินสแตนซ์ของคลาสนั้นขึ้นอยู่กับชีวิตของอินสแตนซ์ของคลาสอื่น ๆ (หรือเหมือนกัน) โดยตรง "อย่าใช้การอ้างอิงเพราะเป็นการป้องกันการมอบหมาย" สมมติว่าคลาสทั้งหมดต้องอนุญาตการกำหนด มันก็เหมือนสมมติว่าทุกชนชั้นต้องอนุญาตให้ดำเนินการคัดลอก ...
Klaim

2

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

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


1
Lakos ยังโต้แย้งเรื่องนี้ใน "การออกแบบซอฟต์แวร์ C ++ ขนาดใหญ่"
Johan Kotlinski

ฉันเชื่อว่า Code Complete สนับสนุนสิ่งนี้เช่นกันและฉันก็ไม่ได้ต่อต้าน มันไม่น่าสนใจจนเกินไป ...
markh44

2

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


0

ถ้าฉันเข้าใจคำถามอย่างถูกต้อง ...

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

การอ้างอิงตัวแปรสมาชิก aa: ดังกล่าวข้างต้นเกี่ยวกับความถูกต้องของข้อมูล สิ่งนี้รับประกันได้ว่าข้อมูลที่ถูกชี้ไปที่อ้างอิงนั้นถูกต้อง

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

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

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

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

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

ฉีกคำตอบนี้ออกไปได้โปรด :)

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