อาร์เรย์เทียบกับเวกเตอร์: ความคล้ายคลึงและความแตกต่างเบื้องต้น [ปิด]


111

อะไรคือความแตกต่างระหว่างอาร์เรย์และเวกเตอร์ใน C ++? ตัวอย่างของความแตกต่างอาจรวมถึงไลบรารีสัญลักษณ์ความสามารถ ฯลฯ

อาร์เรย์

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

- การอ้างอิงกระเป๋า C ++

เวกเตอร์

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

- ตำรา C ++


ความแตกต่างพื้นฐานที่สุด: มีวัตถุประสงค์ที่เวกเตอร์เป็นตัวเลือกที่ดี
Jerry Coffin

1
"หมดจด" และ "ข้อตกลง" เป็นมุมฉาก นั่นคือไม่เพียง แต่ไม่บ่งบอกถึงอีกคนหนึ่งเท่านั้น แต่ยังไม่ได้อยู่ในระดับเดียวกันด้วย
Lightness Races ใน Orbit

2
ฉันรู้สึกไม่สบายใจที่มีคนถามคำถามใกล้ ๆ ซึ่งตรงกับข้อมูลที่ฉันกำลังมองหา สิ่งนี้เกิดขึ้นบ่อยเกินไป
Robert Tamlyn

คำตอบ:


142

อาร์เรย์:

  • เป็นโครงสร้างภาษาในตัว
  • เกือบจะไม่ได้รับการแก้ไขจาก C89;
  • ให้เพียงต่อเนื่องกันตามลำดับที่จัดทำดัชนีขององค์ประกอบ ; ไม่มีระฆังและนกหวีด
  • มีขนาดคงที่ คุณไม่สามารถปรับขนาดอาร์เรย์ใน C ++ ได้ (เว้นแต่จะเป็นอาร์เรย์ของ POD และได้รับการจัดสรรด้วยmalloc)
  • ขนาดของพวกเขาต้องเป็นค่าคงที่เวลาคอมไพล์เว้นแต่จะมีการจัดสรรแบบไดนามิก
  • พวกเขาใช้พื้นที่เก็บข้อมูลขึ้นอยู่กับขอบเขตที่คุณประกาศ
  • หากจัดสรรแบบไดนามิกคุณต้องยกเลิกการจัดสรรอย่างชัดเจน
  • หากมีการจัดสรรแบบไดนามิกคุณจะได้รับตัวชี้และคุณไม่สามารถกำหนดขนาดได้ มิฉะนั้นคุณสามารถใช้sizeof(ด้วยเหตุนี้สำนวนทั่วไปsizeof(arr)/sizeof(*arr)แต่จะล้มเหลวอย่างเงียบ ๆ เมื่อใช้กับตัวชี้โดยไม่ได้ตั้งใจ)
  • สลายตัวเป็นพอยน์เตอร์โดยอัตโนมัติในสถานการณ์ส่วนใหญ่ โดยเฉพาะอย่างยิ่งสิ่งนี้จะเกิดขึ้นเมื่อส่งผ่านไปยังฟังก์ชันซึ่งโดยปกติจะต้องผ่านพารามิเตอร์แยกต่างหากสำหรับขนาดของมัน
  • ไม่สามารถส่งคืนจากฟังก์ชันได้
  • ไม่สามารถคัดลอก / กำหนดได้โดยตรง
  • อาร์เรย์ของวัตถุแบบไดนามิกจำเป็นต้องมีตัวสร้างเริ่มต้นเนื่องจากองค์ประกอบทั้งหมดต้องถูกสร้างขึ้นก่อน

std::vector:

  • เป็นคลาสเทมเพลต
  • เป็นโครงสร้าง C ++ เท่านั้น
  • จะดำเนินการเป็นอาร์เรย์แบบไดนามิก ;
  • เติบโตและหดตัวแบบไดนามิก
  • จัดการหน่วยความจำโดยอัตโนมัติซึ่งเป็นอิสระจากการทำลายล้าง
  • สามารถส่งผ่านไปยัง / ส่งคืนจากฟังก์ชัน (ตามค่า);
  • สามารถคัดลอก / กำหนดได้ (ซึ่งจะทำการคัดลอกองค์ประกอบที่เก็บไว้ทั้งหมดอย่างละเอียด)
  • ไม่ลดลงเป็นตัวชี้ แต่คุณสามารถรับตัวชี้ไปยังข้อมูลได้อย่างชัดเจน ( &vec[0]รับประกันว่าจะทำงานตามที่คาดไว้)
  • มักจะนำมาพร้อมกับอาร์เรย์แบบไดนามิกภายในขนาด (จำนวนองค์ประกอบที่จัดเก็บในปัจจุบัน) และความจุ (จำนวนองค์ประกอบที่สามารถจัดเก็บในบล็อกที่จัดสรรในปัจจุบัน)
  • อาร์เรย์แบบไดนามิกภายในไม่ได้ถูกจัดสรรภายในออบเจ็กต์เอง (ซึ่งมีฟิลด์ "การทำบัญชี" เพียงไม่กี่ฟิลด์) แต่ได้รับการจัดสรรแบบไดนามิกโดยตัวจัดสรรที่ระบุในพารามิเตอร์เทมเพลตที่เกี่ยวข้อง ค่าเริ่มต้นจะได้รับหน่วยความจำจาก freestore (ที่เรียกว่าฮีป) โดยไม่ขึ้นกับวิธีการจัดสรรวัตถุจริง
  • ด้วยเหตุนี้จึงอาจมีประสิทธิภาพน้อยกว่าอาร์เรย์ "ปกติ" สำหรับอาร์เรย์ขนาดเล็กอายุสั้น
  • เมื่อทำการจัดสรรใหม่วัตถุจะถูกคัดลอก (ย้ายใน C ++ 11)
  • ไม่ต้องการตัวสร้างเริ่มต้นสำหรับวัตถุที่จัดเก็บ
  • จะรวมเข้ากับส่วนที่เหลือของสิ่งที่เรียกว่า STL ได้ดีกว่า (มีbegin()/ end()method, STL typedefs ปกติ, ... )

พิจารณา "ทางเลือกที่ทันสมัย" สำหรับอาร์เรย์ด้วย - std::array; ฉันได้อธิบายไว้แล้วในคำตอบอื่นเกี่ยวกับความแตกต่างระหว่างstd::vectorและstd::arrayคุณอาจต้องการดู


1
ขอบคุณ @MatteoItalia อ้างอิงหรือสองจะดี
Trancot

1
@Trancot: หนังสือ C ++ ที่ดีจะทำ
Matteo Italia

6
@Trancot: ฉันไม่สามารถให้ข้อมูลอ้างอิงที่ดีกว่านี้ได้มากนักความแตกต่างที่เน้นในโพสต์นี้มาจากส่วนต่างๆของ Standard และเข้าใจได้ดีขึ้นด้วยความช่วยเหลือของคู่มือ C ++ ที่ดี
Matteo Italia

ตัวอย่างคำอธิบายที่ครอบคลุมจะดีมาก!
carloswm85

26

ฉันจะเพิ่มว่าอาร์เรย์เป็นโครงสร้างระดับต่ำมากใน C ++ และคุณควรพยายามอยู่ห่างจากพวกมันให้มากที่สุดเมื่อ "เรียนรู้เชือก" - แม้แต่ Bjarne Stroustrup ก็แนะนำสิ่งนี้ (เขาเป็นผู้ออกแบบ C ++)

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


1
ส่วนต่อประสานโปรแกรมแอปพลิเคชัน: ( en.wikipedia.org/wiki/API ) เป็นการรวบรวมจุดเข้าสู่เอนทิตีซอฟต์แวร์ (แพ็คเกจไลบรารีระบบปฏิบัติการ) API บางตัวจะมีจุดเข้าเช่น strcat (char * dst, char * src) โดยที่ dst และ src จะถือว่าเป็นอาร์เรย์ของอักขระ (แม้ว่าลายเซ็นฟังก์ชันจะแสดงถึงตัวชี้ไปยังอักขระก็ตาม)
John Källén

11

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

int myArray[100];
myArray[0]=1;
myArray[1]=2;
myArray[2]=3;

สำหรับเวกเตอร์คุณเพียงแค่ประกาศและเพิ่มองค์ประกอบ

vector<int> myVector;
myVector.push_back(1);
myVector.push_back(2);
myVector.push_back(3);
...

ในบางครั้งคุณไม่ทราบจำนวนองค์ประกอบที่ต้องการดังนั้นเวกเตอร์จึงเหมาะสำหรับสถานการณ์เช่นนี้

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