เหตุใดสมาชิกข้อมูลแบบคงที่จึงต้องกำหนดนอกคลาสแยกต่างหากใน C ++ (ไม่เหมือนกับ Java)


41
class A {
  static int foo () {} // ok
  static int x; // <--- needed to be defined separately in .cpp file
};

ฉันไม่เห็นความต้องการในการA::xกำหนดแยกต่างหากในไฟล์. cpp (หรือไฟล์เดียวกันสำหรับแม่แบบ) ทำไมไม่สามารถA::xประกาศและกำหนดในเวลาเดียวกันได้?

มันถูกห้ามด้วยเหตุผลทางประวัติศาสตร์หรือไม่?

คำถามหลักของฉันคือมันจะส่งผลกระทบต่อฟังก์ชั่นใด ๆ หากstaticข้อมูลสมาชิกถูกประกาศ / กำหนดในเวลาเดียวกัน (เช่นเดียวกับJava )?


ตามแนวทางปฏิบัติที่ดีที่สุดโดยทั่วไปแล้วการห่อตัวแปรแบบคงที่ของคุณในวิธีการแบบคงที่ (อาจเป็นแบบคงที่แบบโลคอล) เพื่อหลีกเลี่ยงปัญหาการเริ่มต้นการสั่งซื้อ
Tamás Szelei

2
กฎนี้ผ่อนคลายจริง ๆ เล็กน้อยใน C ++ 11 สมาชิกคงที่ const มักจะไม่จำเป็นต้องกำหนดอีกต่อไป ดู: en.wikipedia.org/wiki/…
mirk

4
@afishwhoswimsaround: การระบุกฎทั่วไปสำหรับทุกสถานการณ์ไม่ใช่ความคิดที่ดี (ควรใช้แนวปฏิบัติที่ดีที่สุดกับบริบท) ที่นี่คุณกำลังพยายามแก้ไขปัญหาที่ไม่มีอยู่ ปัญหาลำดับการเริ่มต้นจะมีผลกับวัตถุที่มีตัวสร้างและเข้าถึงวัตถุระยะเวลาการจัดเก็บแบบคงที่อื่น ๆ เท่านั้น เนื่องจาก 'x' เป็นแบบ int จึงไม่นำมาใช้ครั้งแรกเนื่องจาก 'x' เป็นแบบส่วนบุคคลจึงไม่สามารถใช้งานได้ ประการที่สามสิ่งนี้ไม่เกี่ยวกับคำถาม
Martin York


2
C ++ 17 ช่วยให้การเริ่มต้นอินไลน์สมาชิกข้อมูลแบบคงที่ inline static int x[] = {1, 2, 3};(แม้ชนิดที่ไม่ใช่จำนวนเต็ม): ดู en.cppreference.com/w/cpp/language/static#Static_data_members
Vladimir Reshetnikov

คำตอบ:


15

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

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

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

ตัวอย่างเช่นในGNU Pascalคุณสามารถเขียนหน่วยaในไฟล์a.pasดังนี้:

unit a;

interface

var MyStaticVariable: Integer;

implementation

begin
  MyStaticVariable := 0
end.

โดยที่ตัวแปรโกลบอลถูกประกาศและกำหนดค่าเริ่มต้นในไฟล์ต้นฉบับเดียวกัน

จากนั้นคุณสามารถมีหน่วยต่าง ๆ ที่นำเข้าและใช้ตัวแปรโกลบอล MyStaticVariableเช่นหน่วย b ( b.pas):

unit b;

interface

uses a;

procedure PrintB;

implementation

procedure PrintB;
begin
  Inc(MyStaticVariable);
  WriteLn(MyStaticVariable)
end;
end.

และหน่วย c ( c.pas):

unit c;

interface

uses a;

procedure PrintC;

implementation

procedure PrintC;
begin
  Inc(MyStaticVariable);
  WriteLn(MyStaticVariable)
end;
end.

ในที่สุดคุณสามารถใช้หน่วย b และ c ในโปรแกรมหลักm.pas:

program M;

uses b, c;

begin
  PrintB;
  PrintC;
  PrintB
end.

คุณสามารถรวบรวมไฟล์เหล่านี้แยกกัน:

$ gpc -c a.pas
$ gpc -c b.pas
$ gpc -c c.pas
$ gpc -c m.pas

แล้วสร้างไฟล์ปฏิบัติการด้วย:

$ gpc -o m m.o a.o b.o c.o

และเรียกใช้:

$ ./m
1
2
3

เคล็ดลับที่นี่คือเมื่อคอมไพเลอร์เห็นdirective ใช้ในโมดูลโปรแกรม (เช่นใช้ใน b.pas) มันไม่รวมไฟล์. pas ที่สอดคล้องกัน แต่มองหาไฟล์. gpi เช่นสำหรับรวบรวมไว้ล่วงหน้า ไฟล์อินเตอร์เฟส (ดูเอกสารประกอบ ) .gpiไฟล์เหล่านี้ถูกสร้างโดยคอมไพเลอร์พร้อมกับ.oไฟล์เมื่อแต่ละโมดูลถูกคอมไพล์ ดังนั้นสัญลักษณ์ทั่วโลกถูกกำหนดให้เพียงครั้งเดียวในไฟล์วัตถุMyStaticVariablea.o

Java ทำงานในลักษณะที่คล้ายกันเมื่อนำเข้าแล้วคอมไพเลอร์ชั้นลงไปในชั้น B ก็มีลักษณะที่ไฟล์ระดับสำหรับ A A.javaและไม่จำเป็นต้องใช้ไฟล์ ดังนั้นคำจำกัดความและการกำหนดค่าเริ่มต้นสำหรับคลาส A สามารถใส่ในไฟล์ต้นฉบับไฟล์เดียว

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


42

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

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

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


2
คำถามของฉันไม่ได้เป็นเหตุผลสำหรับพฤติกรรมปัจจุบัน แต่เป็นเหตุผลสำหรับไวยากรณ์ภาษาดังกล่าว กล่าวอีกนัยหนึ่งสมมติว่าstaticมีการประกาศ / กำหนดตัวแปรในที่เดียวกัน (เช่น Java) แล้วจะเกิดอะไรขึ้น?
iammilind

8
@iammilind ฉันคิดว่าคุณไม่เข้าใจว่าจำเป็นต้องใช้ไวยากรณ์เนื่องจากคำอธิบายของคำตอบนี้ ตอนนี้ทำไม เนื่องจากรูปแบบการคอมไพล์ของ C (และ C ++): ไฟล์ c และ cpp เป็นไฟล์รหัสจริงที่คอมไพล์แยกต่างหากเช่นโปรแกรมแยกต่างหากจากนั้นจึงถูกลิงก์เข้าด้วยกันเพื่อให้สามารถเรียกใช้งานได้เต็มรูปแบบ ส่วนหัวไม่ใช่รหัสสำหรับคอมไพเลอร์ แต่เป็นเพียงข้อความที่จะคัดลอกและวางในไฟล์ c และ cpp ตอนนี้หากมีการกำหนดบางสิ่งบางอย่างมันไม่สามารถรวบรวมได้เช่นเดียวกับที่มันจะไม่รวบรวมหากคุณมีตัวแปรโลคอลหลายตัวที่มีชื่อเดียวกัน
Klaim

1
@Klaim แล้วstaticสมาชิกtemplateล่ะ? พวกเขาได้รับอนุญาตในไฟล์ส่วนหัวทั้งหมดตามที่พวกเขาต้องการที่จะมองเห็นได้ ฉันไม่ได้โต้แย้งคำตอบนี้ แต่มันก็ไม่ตรงกับคำถามของฉัน
iammilind

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

2
@iammilind: โดยทั่วไปเทมเพลตจะถูกสร้างอินสแตนซ์ในทุกออบเจ็กต์ไฟล์รวมถึงตัวแปรสแตติก บน Linux ที่มีไฟล์วัตถุของ ELF คอมไพเลอร์จะทำเครื่องหมายอินสแตนซ์เป็นสัญลักษณ์ที่ไม่ รัดกุมซึ่งหมายความว่าลิงเกอร์รวมหลายสำเนาของอินสแตนซ์เดียวกัน เทคโนโลยีเดียวกันนี้สามารถใช้เพื่ออนุญาตการกำหนดตัวแปรสแตติกในไฟล์ส่วนหัวดังนั้นเหตุผลที่ไม่ได้ทำอาจเป็นเพราะการรวมกันของเหตุผลทางประวัติศาสตร์และการพิจารณาประสิทธิภาพการรวบรวม รูปแบบที่รวบรวมทั้งหวังว่าจะได้รับการแก้ไขครั้งต่อไป C ++ มาตรฐานประกอบด้วยโมดูล
ฮัน

6

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

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

สถานการณ์นั้นเป็นไปได้ แต่ต้องการให้ตัวเชื่อมโยงจัดการหลายคำจำกัดความโดยไม่ต้องบ่น

(และโปรดทราบว่าสิ่งนี้ขัดแย้งกับกฎ One Definition เว้นแต่จะสามารถทำได้ตามชนิดของสัญลักษณ์หรือชนิดของส่วนที่วางไว้)


6

มีความแตกต่างอย่างมากระหว่าง C ++ และ Java

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

ใน C ++ ไม่มี "เจ้าของความรู้ขั้นสูงสุด": C ++, C, Fortran Pascal เป็นต้นล้วนเป็น "นักแปล" จากซอร์สโค้ด (ไฟล์ CPP) ในรูปแบบสื่อกลาง (ไฟล์ OBJ หรือไฟล์ ".o" ขึ้นอยู่กับ OS) ที่คำสั่งถูกแปลเป็นคำสั่งเครื่องและชื่อจะกลายเป็นที่อยู่ทางอ้อมซึ่งสื่อกลางโดยตารางสัญลักษณ์

โปรแกรมไม่ได้ทำโดยคอมไพเลอร์ แต่เป็นอีกโปรแกรมหนึ่ง ("linker") ที่รวม OBJ-s ทั้งหมดเข้าด้วยกัน (ไม่ว่าพวกเขาจะมาจากภาษาใด) โดยการชี้ที่อยู่ทั้งหมดที่มีต่อสัญลักษณ์ของพวกเขา คำจำกัดความที่มีประสิทธิภาพ

โดยวิธีการทำงานของ linker คำจำกัดความ (สิ่งที่สร้างพื้นที่ทางกายภาพสำหรับตัวแปร) จะต้องไม่ซ้ำกัน

โปรดทราบว่า C ++ ไม่ได้เชื่อมโยงด้วยตัวเองและตัวเชื่อมโยงไม่ได้ออกโดยข้อกำหนด C ++: ตัวเชื่อมโยงนั้นมีอยู่เนื่องจากวิธีการสร้างโมดูลระบบปฏิบัติการ (โดยปกติจะอยู่ใน C และ ASM) C ++ ต้องใช้อย่างที่เป็นอยู่

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

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

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

หากมีหลายคำจำกัดความ (อย่าสับสนกับคำที่อ้างอิง) สำหรับสัญลักษณ์ที่ระบุ linker ไม่มีความรู้ (เป็นผู้ไม่เชื่อเรื่องภาษา) เกี่ยวกับสิ่งที่จะทำกับพวกเขา

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


3
ความแตกต่างระหว่าง Java และ C ++ ที่เกี่ยวข้องกับสัญลักษณ์ทั่วโลกไม่ได้เชื่อมต่อกับ Java ที่มีเครื่องเสมือน แต่ใช้กับรูปแบบการคอมไพล์ C ++ ในส่วนนี้ฉันจะไม่ใส่ Pascal และ C ++ ในหมวดหมู่เดียวกัน ค่อนข้างฉันจะจัดกลุ่ม C และ C ++ ร่วมกันเป็น "ภาษาที่มีการประกาศการนำเข้ารวมและรวบรวมพร้อมกับไฟล์ต้นฉบับ" เมื่อเทียบกับ Java และ Pascal (และอาจจะเป็น OCaml, Scala, Ada และอื่น ๆ ) เป็น "ภาษาที่ การประกาศที่อิมพอร์ตจะถูกค้นหาโดยคอมไพเลอร์ในไฟล์ที่รวบรวมไว้ล่วงหน้าซึ่งมีข้อมูลเกี่ยวกับสัญลักษณ์ที่ส่งออก "
Giorgio

1
@Giorgio: การอ้างอิงถึง Java อาจไม่ได้รับการต้อนรับ แต่ฉันคิดว่าคำตอบของ Emilio นั้นส่วนใหญ่จะถูกต้องโดยการสรุปสาระสำคัญของปัญหาคือไฟล์อ็อบเจ็กต์ / เฟสลิงก์หลังจากการรวบรวมแยกกัน
ixache

5

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

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


2

ฉันคิดว่าฉันพบเหตุผล การกำหนดstaticตัวแปรในพื้นที่แยกช่วยให้สามารถเริ่มต้นเป็นค่าใด ๆ หากไม่ได้กำหนดค่าเริ่มต้นระบบจะใช้ค่าเริ่มต้นเป็น 0

ก่อน C ++ 11 ไม่อนุญาตให้เริ่มต้นในคลาสใน C ++ ดังนั้นจึงไม่สามารถเขียนเช่น:

struct X
{
  static int i = 4;
};

ดังนั้นตอนนี้เพื่อเริ่มต้นตัวแปรหนึ่งจะต้องเขียนมันนอกชั้นเรียนเป็น:

struct X
{
  static int i;
};
int X::i = 4;

ดังที่กล่าวไว้ในคำตอบอื่น ๆ ด้วยint X::iตอนนี้เป็นโกลบอลและการประกาศโกลบอลในไฟล์จำนวนมากทำให้เกิดข้อผิดพลาดลิงก์สัญลักษณ์หลายอัน

ดังนั้นเราจึงต้องประกาศstaticตัวแปรคลาสภายในหน่วยการแปลที่แยกต่างหาก อย่างไรก็ตามยังคงเป็นที่ถกเถียงกันอยู่ว่าวิธีต่อไปนี้ควรแนะนำคอมไพเลอร์ไม่ให้สร้างหลายสัญลักษณ์

static int X::i = 4;
^^^^^^

0

A :: x เป็นเพียงตัวแปรส่วนกลาง แต่เนมสเปซจะเป็น A และมีข้อ จำกัด ในการเข้าถึง

บางคนยังคงต้องประกาศเช่นเดียวกับตัวแปรทั่วโลกอื่น ๆ และอาจทำได้ในโครงการที่เชื่อมโยงกับโครงการที่มีรหัส A ส่วนที่เหลือ

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

  1. ตัวสร้างคำสั่งเรียก ... ไม่สำคัญสำหรับ int แต่สำหรับสมาชิกที่ซับซ้อนมากขึ้นซึ่งอาจเข้าถึงตัวแปรคงที่หรือตัวแปรอื่น ๆ ทั่วโลกก็อาจเป็นสิ่งสำคัญ

  2. static initializer - คุณสามารถให้ไคลเอนต์ตัดสินใจว่า A :: x ควรถูกเตรียมใช้งาน

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

ฉันสงสัยว่าสิ่งเหล่านี้คือ "สาเหตุ" สถานการณ์นี้เกิดขึ้น มันอาจเป็นเพียงวิวัฒนาการของ C กลายเป็น C ++ และปัญหาความเข้ากันได้แบบย้อนหลังที่หยุดคุณจากการเปลี่ยนภาษาในขณะนี้


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