เหตุใด C และ C ++ จึงสนับสนุนการกำหนดอาร์เรย์แบบสมาชิกภายในโครงสร้าง แต่โดยทั่วไปแล้วไม่ใช่


87

ฉันเข้าใจว่าไม่รองรับการกำหนดอาร์เรย์แบบสมาชิกดังนั้นสิ่งต่อไปนี้จะใช้ไม่ได้:

int num1[3] = {1,2,3};
int num2[3];
num2 = num1; // "error: invalid array assignment"

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

อย่างไรก็ตามสิ่งต่อไปนี้ใช้งานได้:

struct myStruct { int num[3]; };
struct myStruct struct1 = {{1,2,3}};
struct myStruct struct2;
struct2 = struct1;

อาร์เรย์num[3]เป็นสมาชิกที่กำหนดจากอินสแตนซ์ในstruct1อินสแตนซ์ในstruct2.

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

แก้ไข : ความคิดเห็นของRoger Pateในเธรดstd :: string ใน struct - ปัญหาการคัดลอก / การกำหนด? ดูเหมือนจะชี้ไปในทิศทางทั่วไปของคำตอบ แต่ฉันไม่รู้เพียงพอที่จะยืนยันด้วยตัวเอง

แก้ไข 2 : คำตอบที่ยอดเยี่ยมมากมาย ฉันเลือกLuther Blissettเพราะส่วนใหญ่ฉันสงสัยเกี่ยวกับเหตุผลทางปรัชญาหรือประวัติศาสตร์ที่อยู่เบื้องหลังพฤติกรรม แต่การอ้างอิงของJames McNellisไปยังเอกสารข้อมูลจำเพาะที่เกี่ยวข้องก็มีประโยชน์เช่นกัน


6
ฉันทำให้สิ่งนี้มีทั้ง C และ C ++ เป็นแท็กเพราะสิ่งนี้มาจาก C เช่นกันเป็นคำถามที่ดี
GManNickG

4
อาจเป็นที่น่าสังเกตว่าเมื่อนานมาแล้วในภาษา C การกำหนดโครงสร้างไม่สามารถทำได้โดยทั่วไปและคุณต้องใช้memcpy()หรือคล้ายกัน
ggg

FYI เพียงเล็กน้อย ... boost::array( boost.org/doc/libs/release/doc/html/array.html ) และตอนนี้std::array( en.cppreference.com/w/cpp/container/array ) เป็นทางเลือกที่เข้ากันได้กับ STL สำหรับ อาร์เรย์ C เก่าที่ยุ่งเหยิง รองรับการกำหนดสำเนา
Emile Cormier

@EmileCormier และพวกเขาคือ - ธาดา! - โครงสร้างรอบอาร์เรย์
ปีเตอร์ - คืนสถานะโมนิกา

คำตอบ:


46

นี่คือสิ่งที่ฉันทำ:

การพัฒนาภาษาซีนำเสนอข้อมูลเชิงลึกเกี่ยวกับวิวัฒนาการของประเภทอาร์เรย์ใน C:

ฉันจะพยายามร่างสิ่งอาร์เรย์:

บรรพบุรุษของ C B และ BCPL ไม่มีประเภทอาร์เรย์ที่แตกต่างกันการประกาศเช่น:

auto V[10] (B)
or 
let V = vec 10 (BCPL)

จะประกาศให้ V เป็นตัวชี้ (ไม่ได้พิมพ์) ซึ่งเริ่มต้นให้ชี้ไปยังส่วนที่ไม่ได้ใช้ของหน่วยความจำ 10 "คำ" B ใช้แล้ว*สำหรับการอ้างอิงตัวชี้และมี[] สัญกรณ์แบบมือสั้น*(V+i)หมายถึงV[i]เช่นเดียวกับใน C / C ++ ในปัจจุบัน อย่างไรก็ตามVไม่ใช่อาร์เรย์ แต่ยังคงเป็นตัวชี้ที่ต้องชี้ไปที่หน่วยความจำบางส่วน สิ่งนี้ทำให้เกิดปัญหาเมื่อ Dennis Ritchie พยายามขยาย B ด้วยประเภทของโครงสร้าง เขาต้องการให้อาร์เรย์เป็นส่วนหนึ่งของโครงสร้างเช่นใน C วันนี้:

struct {
    int inumber;
    char name[14];
};

แต่ด้วยแนวคิด B, BCPL ของอาร์เรย์เป็นตัวชี้สิ่งนี้จะต้องให้nameฟิลด์มีตัวชี้ที่ต้องเริ่มต้นเมื่อรันไทม์เป็นพื้นที่หน่วยความจำ 14 ไบต์ภายในโครงสร้าง ในที่สุดปัญหาการกำหนดค่าเริ่มต้น / เค้าโครงได้รับการแก้ไขโดยการให้การดูแลเป็นพิเศษกับอาร์เรย์: คอมไพเลอร์จะติดตามตำแหน่งของอาร์เรย์ในโครงสร้างบนสแต็ก ฯลฯ โดยไม่ต้องใช้ตัวชี้ไปยังข้อมูลเพื่อให้เป็นจริงยกเว้นในนิพจน์ที่เกี่ยวข้องกับอาร์เรย์ การรักษานี้ได้รับอนุญาตเกือบรหัส B ทั้งหมดเรียกใช้และยังคงเป็นแหล่งที่มาของ"อาร์เรย์แปลงเป็นตัวชี้ถ้าคุณมองไปที่พวกเขา"กฎ เป็นการแฮ็คที่เข้ากันได้ซึ่งกลายเป็นประโยชน์อย่างมากเนื่องจากอนุญาตให้มีอาร์เรย์ขนาดเปิด

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

auto V[10];
V=V+5;

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

/* Example how array assignment void make things even weirder in C/C++, 
   if we don't want to break existing code.
   It's actually better to leave things as they are...
*/
typedef int vec[3];

void f(vec a, vec b) 
{
    vec x,y; 
    a=b; // pointer assignment
    x=y; // NEW! element-wise assignment
    a=x; // pointer assignment
    x=a; // NEW! element-wise assignment
}

สิ่งนี้ไม่เปลี่ยนแปลงเมื่อมีการแก้ไข C ในปี 1978 เพิ่มการกำหนดโครงสร้าง ( http://cm.bell-labs.com/cm/cs/who/dmr/cchanges.pdf ) แม้ว่าระเบียนจะเป็นประเภทที่แตกต่างกันใน C แต่ก็ไม่สามารถกำหนดได้ในช่วงต้น K&R C คุณต้องคัดลอกแบบสมาชิกที่ชาญฉลาดด้วย memcpy และคุณสามารถส่งเฉพาะพอยน์เตอร์ไปให้เป็นพารามิเตอร์ฟังก์ชันได้ การกำหนด (และการส่งผ่านพารามิเตอร์) ถูกกำหนดให้เป็น memcpy ของหน่วยความจำดิบของโครงสร้างและเนื่องจากสิ่งนี้ไม่สามารถทำลายโค้ดที่มีอยู่ได้จึงถูกนำมาใช้อย่างง่ายดาย ในฐานะที่เป็นผลข้างเคียงที่ไม่ได้ตั้งใจสิ่งนี้ได้นำเสนอการกำหนดอาร์เรย์บางประเภทโดยปริยาย แต่สิ่งนี้เกิดขึ้นที่ไหนสักแห่งภายในโครงสร้างดังนั้นจึงไม่สามารถทำให้เกิดปัญหากับวิธีการใช้อาร์เรย์


มันแย่เกินไปที่ C ไม่ได้กำหนดไวยากรณ์เช่นint[10] c;ทำให้ lvalue cทำงานเป็นอาร์เรย์สิบรายการแทนที่จะเป็นตัวชี้ไปยังรายการแรกของอาร์เรย์สิบรายการ มีบางสถานการณ์ที่มีประโยชน์ในการสร้าง typedef ที่จัดสรรพื้นที่เมื่อใช้สำหรับตัวแปร แต่จะส่งผ่านตัวชี้เมื่อใช้เป็นอาร์กิวเมนต์ของฟังก์ชัน แต่การไม่สามารถระบุค่าประเภทอาร์เรย์ได้ถือเป็นจุดอ่อนทางความหมายที่สำคัญ ในภาษา
supercat

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

ดูการเกลียดชังอาร์เรย์ของ Cสำหรับข้อมูลสรุปที่ดีของประวัติศาสตร์
Peter Cordes

31

เกี่ยวกับตัวดำเนินการกำหนดมาตรฐาน C ++ กล่าวว่าต่อไปนี้ (C ++ 03 §5.17 / 1):

มีตัวดำเนินการกำหนดหลายตัว ... ทั้งหมดต้องการ lvalue ที่ปรับเปลี่ยนได้เป็นตัวถูกดำเนินการด้านซ้าย

อาร์เรย์ไม่ใช่ค่า lvalue ที่ปรับเปลี่ยนได้

อย่างไรก็ตามการกำหนดให้กับออบเจ็กต์ประเภทคลาสถูกกำหนดไว้เป็นพิเศษ (§5.17 / 4):

การกำหนดให้กับออบเจ็กต์ของคลาสถูกกำหนดโดยตัวดำเนินการกำหนดสำเนา

ดังนั้นเรามาดูกันว่าตัวดำเนินการกำหนดสำเนาที่ประกาศโดยนัยสำหรับชั้นเรียนทำอะไรบ้าง (§12.8 / 13):

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

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


การให้เหตุผลคล้ายกันใน C (C99 §6.5.16 / 2):

ผู้ดำเนินการมอบหมายจะต้องมี modi i สามารถ lvalue เป็นตัวถูกดำเนินการด้านซ้าย

และ§6.3.2.1 / 1:

lvalue modi fi able คือ lvalue ที่ไม่มีประเภทอาร์เรย์ ... [มีข้อ จำกัด อื่น ๆ ตามมา]

ใน C การกำหนดง่ายกว่า C ++ (++6.5.16.1 / 2) มาก:

ในการกำหนดอย่างง่าย (=) ค่าของตัวถูกดำเนินการด้านขวาจะถูกแปลงเป็นประเภทของนิพจน์การกำหนดและแทนที่ค่าที่เก็บไว้ในวัตถุที่กำหนดโดยตัวถูกดำเนินการด้านซ้าย

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


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

1
@GMan: นั่นเป็นคำถามที่น่าสนใจกว่าใช่ไหม สำหรับ C ++ คำตอบน่าจะเป็น "เพราะมันเป็นอย่างไรในภาษา C" และสำหรับ C ฉันเดาว่ามันเป็นเพราะการพัฒนาของภาษา (กล่าวคือเหตุผลเป็นเรื่องทางประวัติศาสตร์ไม่ใช่ทางเทคนิค) แต่ฉันไม่ได้มีชีวิตอยู่ เมื่อส่วนใหญ่เกิดขึ้นดังนั้นฉันจะปล่อยให้คนที่มีความรู้มากกว่าเพื่อตอบส่วนนั้น :-P (FWIW ฉันไม่พบสิ่งใดในเอกสารเหตุผล C90 หรือ C99)
James McNellis

2
มีใครทราบบ้างว่าคำจำกัดความของ "lvalue ที่ปรับเปลี่ยนได้" อยู่ที่ใดในมาตรฐาน C ++ 03? มันควรจะอยู่ใน§3.10 ดัชนีระบุว่ามีการกำหนดไว้ในหน้านั้น แต่ไม่ใช่ หมายเหตุ (non-normative) ที่§8.3.4 / 5 ระบุว่า "ไม่สามารถแก้ไขออบเจ็กต์ประเภทอาร์เรย์ได้โปรดดูที่ 3.10" แต่§3.10ไม่ได้ใช้คำว่า "array"
James McNellis

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

1
@GMan, James: เมื่อเร็ว ๆ นี้มีการสนทนาเกี่ยวกับ comp.lang.c ++ groups.google.com/group/comp.lang.c++/browse_frm/thread/…หากคุณพลาดและยังคงสนใจ เห็นได้ชัดว่าไม่ใช่เพราะอาร์เรย์ไม่ใช่ lvalue ที่ปรับเปลี่ยนได้ (อาร์เรย์แน่นอนเป็น lvalue และ lvalue ที่ไม่ใช่ const ทั้งหมดสามารถแก้ไขได้) แต่เนื่องจาก=ต้องใช้rvalueในRHSและอาร์เรย์ไม่สามารถเป็นค่าrvalue ได้ ! การแปลง lvalue-to-rvalue ไม่ได้รับอนุญาตสำหรับอาร์เรย์แทนที่ด้วย lvalue-to-pointer static_castไม่มีอะไรดีไปกว่าการสร้าง rvalue เพราะถูกกำหนดในเงื่อนไขเดียวกัน
Potatoswatter

2

ในลิงค์นี้: http://www2.research.att.com/~bs/bs_faq2.html มีส่วนในการกำหนดอาร์เรย์:

ปัญหาพื้นฐานสองประการเกี่ยวกับอาร์เรย์คือ

  • อาร์เรย์ไม่ทราบขนาดของตัวเอง
  • ชื่อของอาร์เรย์จะแปลงเป็นตัวชี้ไปยังองค์ประกอบแรกโดยมีการยั่วยุน้อยที่สุด

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

ดังนั้นคอมไพเลอร์ไม่สามารถบอกความแตกต่างระหว่าง int a [10] และ int b [20] ได้

อย่างไรก็ตามโครงสร้างไม่มีความคลุมเครือเหมือนกัน


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

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

3
คอมไพเลอร์สามารถบอกความแตกต่างระหว่างสองอาร์เรย์ขนาดแตกต่างกัน - ลองพิมพ์sizeof(a)กับsizeof(b)หรือผ่านไปa void f(int (&)[20]);
Georg Fritzsche

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

0

ฉันรู้ว่าทุกคนที่ตอบเป็นผู้เชี่ยวชาญใน C / C ++ แต่ฉันคิดว่านี่เป็นเหตุผลหลัก

num2 = num1;

ที่นี่คุณกำลังพยายามเปลี่ยนที่อยู่ฐานของอาร์เรย์ซึ่งไม่ได้รับอนุญาต

และแน่นอน struct2 = struct1;

ที่นี่วัตถุ struct1 ถูกกำหนดให้กับวัตถุอื่น


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

1
ตกลง แต่คอมไพเลอร์ตัวแรกป้องกันไว้ (num2 = num1) คอมไพเลอร์ที่สองไม่ได้ป้องกัน นั่นสร้างความแตกต่างอย่างมาก
nsivakr

หากสามารถกำหนดอาร์เรย์ได้num2 = num1จะมีการทำงานที่ดีอย่างสมบูรณ์ องค์ประกอบของจะมีค่าเดียวกันขององค์ประกอบที่สอดคล้องกันของnum2 num1
juanchopanza

0

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

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

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