Khi các vectơ được phân bổ, chúng có sử dụng bộ nhớ trên heap hoặc stack không?


151

Có phải tất cả các tuyên bố sau đây là đúng?

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. 

Bộ nhớ được phân bổ nội bộ Typetrong một vectorhoặc bất kỳ container STL nào khác?


Câu trả lời:


221
vector<Type> vect;

sẽ phân bổ vector, tức là thông tin tiêu đề, trên ngăn xếp, nhưng các yếu tố trên cửa hàng miễn phí ("heap").

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

phân bổ mọi thứ trên cửa hàng miễn phí.

vector<Type*> vect;

sẽ phân bổ vectortrên ngăn xếp và một loạt các con trỏ trên cửa hàng miễn phí, nhưng ở đó những điểm này được xác định bằng cách bạn sử dụng chúng (bạn có thể trỏ phần tử 0 vào cửa hàng miễn phí và phần tử 1 vào ngăn xếp, giả sử).


3
Nhưng tôi đang có một kịch bản, nơi tôi đang gặp lỗi phân khúc khi Type đang phát triển lớn trên tuyên bố thứ hai. Tôi đã cho rằng đó là vì Type đã được phân bổ trên stack.
Phelodas

4
@Phelodas: không thấy mã của bạn, điều này là không thể đánh giá. Hãy mở một câu hỏi mới.
Fred Foo

2
Giới thiệu vector<Type> vect;vì các phần tử nằm trong heap và thông tin tiêu đề nằm trên ngăn xếp, khi thông tin tiêu đề bị xóa khỏi bộ nhớ, như trả về hàm, điều gì sẽ xảy ra với các phần tử bộ nhớ? Họ có được khai hoang với thông tin tiêu đề hay không? Nếu họ không, điều này sẽ gây rò rỉ bộ nhớ?
flyrain

3
@flyrain: vectơ dọn dẹp sau khi chính họ. Đọc lên trên RAII .
Fred Foo

1
@flyrain: nên hoạt động. Xin vui lòng gửi một câu hỏi mới với nhiều chi tiết hơn. Nếu bạn đăng liên kết ở đây, tôi có thể xem nó.
Fred Foo

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

Không, vectsẽ nằm trên stack, nhưng mảng nó sử dụng bên trong để lưu trữ các mục sẽ nằm trong heap. Các mục sẽ nằm trong mảng đó.

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

Không. Giống như trên, ngoại trừ vectorlớp cũng sẽ ở trên đống.

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

vectsẽ ở trên ngăn xếp, các mục của nó (con trỏ tới Type) sẽ nằm trên đống, và bạn không thể biết nơi nào sẽ là Typecon trỏ trỏ tới. Có thể là trên stack, có thể là trên heap, có thể là trong dữ liệu toàn cầu, có thể là hư không (ví dụ: NULLcon trỏ).

BTW thực hiện trên thực tế có thể lưu trữ một số vectơ (thường có kích thước nhỏ) trên ngăn xếp hoàn toàn. Không phải tôi biết về bất kỳ thực hiện như vậy, nhưng nó có thể.


23

Giả sử một triển khai thực sự có một ngăn xếp và một đống (C ++ tiêu chuẩn không yêu cầu phải có những thứ như vậy) thì tuyên bố đúng duy nhất là tuyên bố cuối cùng.

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

Điều này là đúng, ngoại trừ phần cuối cùng ( Typesẽ không nằm trong ngăn xếp). Hãy tưởng tượng:

  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);
  }

Tương tự như vậy:

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

Đúng ngoại trừ phần cuối cùng, với một ví dụ truy cập tương tự:

  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);
  }

Dành cho:

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

Điều này là đúng, nhưng lưu ý ở đây là các Type*con trỏ sẽ nằm trong heap, nhưng các Typetrường hợp chúng chỉ ra không cần phải là:

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

trong bối cảnh nào bạn sẽ không có một ngăn xếp? Tôi hiểu rằng bạn đang nói tiêu chuẩn không yêu cầu nó, nhưng thực tế mà nói, khi nào bạn sẽ không có chồng?
Nerdtron

3
@Nerdtron - IIRC trên một số bộ vi điều khiển nhỏ, bạn có một ngăn xếp cuộc gọi không thể lưu trữ gì ngoài PC (bộ đếm chương trình) tại điểm của cuộc gọi cuối cùng, sẵn sàng cho RET. Do đó, trình biên dịch của bạn có thể chọn đặt "lưu trữ tự động" (cho các hàm không đệ quy) ở một vị trí cố định với rất ít / không liên quan đến luồng thực thi. Nó hoàn toàn có thể san phẳng toàn bộ chương trình. Ngay cả đối với trường hợp đệ quy, bạn có thể có chính sách "ngăn xếp theo hàm" hoặc ngăn xếp riêng cho các biến tự động và địa chỉ trả về, điều này làm cho cụm từ "ngăn xếp" trở nên vô nghĩa.
Flexo

Bạn có thể sử dụng phân bổ dựa trên heap cho mọi thứ và có một "ngăn xếp dọn dẹp" để quản lý lưu trữ tự động (và có thể deletecũng vậy).
Flexo

3

Chỉ tuyên bố này là đúng:

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

Type* con trỏ được phân bổ trên heap, bởi vì số lượng con trỏ có thể thay đổi linh hoạt.

vect trong trường hợp này được phân bổ trên ngăn xếp, bởi vì bạn đã xác định nó là biến ngăn xếp cục bộ.


2
Loại * không biểu thị phân bổ heap, chỉ đơn giản là một con trỏ tới đối tượng Loại. Điều đó nói rằng, vector không lưu trữ con trỏ trên heap. int a = 5; int * ptr_to_a = & a; vectơ <int *> vec; vec.push_back (ptr_to_a); (xem câu trả lời của jpalecek)
Matthew Russell

1

vector có một nội bộ allocatorchịu trách nhiệm phân bổ / giải phóng các ký ức từ heapcho vector element. Vì vậy, bất kể bạn tạo một vectơ như thế nào, nó elementluôn được phân bổ trên heap. Đối với siêu dữ liệu của vectơ, nó phụ thuộc vào cách bạn tạo nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.