เมื่อมีการจัดสรรเวกเตอร์พวกเขาจะใช้หน่วยความจำบนกองหรือกอง?


151

ข้อความต่อไปนี้ทั้งหมดเป็นจริงหรือไม่?

vector<Type> vect; //allocates vect on stack and each of the Type (using std::allocator) also will be on the stack

vector<Type> *vect = new vector<Type>; //allocates vect on heap and each of the Type will be allocated on stack

vector<Type*> vect; //vect will be on stack and Type* will be on heap. 

เป็นวิธีการจัดสรรหน่วยความจำภายในสำหรับTypeในvectorหรือภาชนะ STL อื่น ๆ ?


คำตอบ:


222
vector<Type> vect;

จะจัดสรรvectorเช่นข้อมูลส่วนหัวในสแต็ก แต่องค์ประกอบในร้านค้าฟรี ("ฮีป")

vector<Type> *vect = new vector<Type>;

จัดสรรทุกอย่างในร้านค้าฟรี

vector<Type*> vect;

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


3
แต่ฉันกำลังมีสถานการณ์ที่ฉันได้รับข้อผิดพลาดการแบ่งส่วนเมื่อ Type มีขนาดใหญ่ขึ้นในการประกาศครั้งที่สอง ฉันสมมติว่าเป็นเพราะ Type ถูกจัดสรรใน stack
Phelodas

4
@Perodas: หากไม่เห็นรหัสของคุณคุณจะไม่สามารถประเมินได้ โปรดเปิดคำถามใหม่
Fred Foo

2
เกี่ยวกับvector<Type> vect;เนื่องจากองค์ประกอบที่อยู่ในกองและข้อมูลส่วนหัวอยู่ในกองเมื่อข้อมูลส่วนหัวจะถูกลบออกจากหน่วยความจำเช่นฟังก์ชั่นกลับมาจะเกิดอะไรขึ้นกับความทรงจำองค์ประกอบ? พวกเขาจะเรียกคืนด้วยข้อมูลส่วนหัวหรือไม่? หากไม่ใช่จะทำให้หน่วยความจำรั่วหรือไม่
flyrain

3
@ แมลงวัน: เวกเตอร์ทำความสะอาดหลังจากที่ตัวเอง อ่านข้อมูลเกี่ยวกับRAII
Fred Foo

1
@ แมลงวัน: มันควรจะทำงาน โปรดโพสต์คำถามใหม่พร้อมรายละเอียดเพิ่มเติม หากคุณโพสต์ลิงค์ที่นี่ฉันอาจจะดู
Fred Foo

25
vector<Type> vect; //allocates vect on stack and each of the Type (using std::allocator) also will be on the stack

ไม่vectจะอยู่ในสแต็ก แต่อาร์เรย์ที่ใช้ภายในเพื่อเก็บรายการจะอยู่ในฮีป รายการจะอยู่ในอาร์เรย์นั้น

vector<Type> *vect = new vector<Type>; //allocates vect on heap and each of the Type will be allocated on stack

ไม่เหมือนข้างบนยกเว้นvectorชั้นเรียนจะอยู่บนกองเช่นกัน

vector<Type*> vect; //vect will be on stack and Type* will be on heap. 

vectจะอยู่ในสแต็กรายการของมัน (ตัวชี้ไปยังType) จะอยู่บนฮีปและคุณไม่สามารถบอกได้ว่าTypeตัวชี้จะชี้ไปที่ใด อาจอยู่ใน stack อาจเป็น heap อาจอยู่ในข้อมูลส่วนกลางอาจไม่มีที่ไหนเลย (เช่น. NULLpointers)

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


23

สมมติว่ามีการนำไปใช้งานซึ่งจริง ๆ แล้วมีกองและกอง (c ++ มาตรฐานทำให้ไม่มีความต้องการที่จะมีสิ่งต่าง ๆ ) ข้อความจริงเพียงอย่างเดียวคือคนสุดท้าย

vector<Type> vect;
//allocates vect on stack and each of the Type (using std::allocator) also will be on the stack

สิ่งนี้เป็นจริงยกเว้นส่วนสุดท้าย ( Typeจะไม่อยู่ในสแต็ก) Imagine:

  void foo(vector<Type>& vec) {
     // Can't be on stack - how would the stack "expand"
     // to make the extra space required between main and foo?
     vec.push_back(Type());
  }

  int main() {
    vector<Type> bar;
    foo(bar);
  }

ในทำนองเดียวกัน:

 vector<Type> *vect = new vector<Type>; //allocates vect on heap and each of the Type will be allocated on stack

True ยกเว้นส่วนสุดท้ายพร้อมด้วยตัวนับที่คล้ายกัน:

  void foo(vector<Type> *vec) {
     // Can't be on stack - how would the stack "expand"
     // to make the extra space required between main and foo?
     vec->push_back(Type());
  }

  int main() {
    vector<Type> *bar = new vector<Type>;
    foo(bar);
  }

สำหรับ:

vector<Type*> vect; //vect will be on stack and Type* will be on heap. 

นี่เป็นความจริง แต่โปรดสังเกตที่นี่ว่าพType*อยน์เตอร์จะอยู่บนฮีป แต่Typeอินสแตนซ์ที่ชี้ไปไม่จำเป็นต้องเป็น:

  int main() {
    vector<Type*> bar;
    Type foo;
    bar.push_back(&foo);
  }

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

3
@Nerdtron - IIRC บนไมโครคอนโทรลเลอร์ขนาดเล็กบางตัวคุณมี call stack ที่ไม่สามารถเก็บอะไรไว้นอกจาก PC (โปรแกรมตัวนับ) ณ จุดที่โทรล่าสุดพร้อมสำหรับ RET คอมไพเลอร์ของคุณอาจเลือกที่จะ "จัดเก็บอัตโนมัติ" (สำหรับฟังก์ชั่นที่ไม่เกิดซ้ำ) ในสถานที่คงที่ที่มีความสัมพันธ์เพียงเล็กน้อย / ไม่เกี่ยวข้องกับการไหลของการดำเนินการ มันอาจทำให้โปรแกรมทั้งหมดแบน แม้แต่ในกรณีที่เกิดซ้ำคุณอาจมีนโยบาย "สแต็กต่อฟังก์ชัน" หรือสแต็กแยกต่างหากสำหรับตัวแปรอัตโนมัติและที่อยู่ผู้ส่งซึ่งทำให้วลี "สแต็ก" ไม่มีความหมาย
Flexo

คุณสามารถใช้การจัดสรรแบบอิงฮีปสำหรับทุกสิ่งและมี "สแต็กการล้างข้อมูล" ที่จัดการที่เก็บข้อมูลอัตโนมัติ (และอาจdeleteเกินไป)
เฟล็กโซ

3

เฉพาะข้อความนี้เท่านั้นที่เป็นจริง:

vector <Type*> vect; //vect will be on stack and Type* will be on heap.

Type* พอยน์เตอร์ได้รับการจัดสรรบนฮีปเนื่องจากจำนวนพอยน์เตอร์สามารถเปลี่ยนแปลงได้แบบไดนามิก

vect ในกรณีนี้ได้รับการจัดสรรในสแต็กเพราะคุณกำหนดเป็นตัวแปรสแต็คท้องถิ่น


2
Type * ไม่ได้ระบุการจัดสรรฮีปเพียงแค่ตัวชี้ไปยังวัตถุ Type ที่กล่าวว่าเวกเตอร์เก็บตัวชี้ไว้บนกอง int a = 5; int * ptr_to_a = & a; เวกเตอร์ <int *> vec; vec.push_back (ptr_to_a); (ดูคำตอบของ jpalecek)
Matthew Russell

1

เวกเตอร์มีภายในallocatorซึ่งเป็นค่าใช้จ่ายในการจัดสรร / deallocating จากความทรงจำสำหรับheap vector elementดังนั้นไม่ว่าคุณจะสร้างเวกเตอร์ของมันจะถูกจัดสรรเสมอในelement heapสำหรับเมตาดาต้าของเวกเตอร์นั้นขึ้นอยู่กับวิธีที่คุณสร้าง

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