Quando os vetores são alocados, eles usam memória na pilha ou na pilha?

151

Todas as seguintes afirmações são verdadeiras?

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. 

Como a memória é alocada internamente para Typeum vectorou qualquer outro contêiner STL?

Phelodas
fonte
1
Possível duplicata de membros
underscore_d

Respostas:

221
vector<Type> vect;

alocará a vector, ou seja, as informações do cabeçalho, na pilha, mas os elementos no armazenamento gratuito ("heap").

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

aloca tudo na loja gratuita.

vector<Type*> vect;

alocará o vectorna pilha e vários ponteiros no armazenamento gratuito, mas onde esses pontos são determinados pela maneira como você os usa (você pode apontar o elemento 0 para o armazenamento gratuito e o elemento 1 para a pilha, digamos).

Fred Foo
fonte
3
Mas estou tendo um cenário em que estou recebendo uma falha de segmentação quando Type está crescendo muito na segunda declaração. Eu estava assumindo que era porque Type estava sendo alocado na pilha.
Phelodas
4
@ Phelodas: sem ver seu código, isso é impossível de avaliar. Por favor, abra uma nova pergunta.
Fred Foo
2
Sobre vector<Type> vect;como os elementos estão na pilha e as informações do cabeçalho estão na pilha, quando as informações do cabeçalho são removidas da memória, como o retorno da função, o que acontecerá com as memórias dos elementos? Eles são recuperados com as informações do cabeçalho ou não? Caso contrário, isso causará vazamento de memória?
precisa saber é o seguinte
3
@flyrain: vetores limpam depois de si mesmos. Leia sobre o RAII .
Fred Foo
1
@ flyrain: isso deve funcionar. Poste uma nova pergunta com mais detalhes. Se você postar o link aqui, eu posso dar uma olhada nele.
22813 Fred Foo
25
vector<Type> vect; //allocates vect on stack and each of the Type (using std::allocator) also will be on the stack

Não, vectestará na pilha, mas a matriz que ela usa internamente para armazenar os itens estará na pilha. Os itens residirão nessa matriz.

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

Não. O mesmo que acima, exceto que a vectorclasse também estará na pilha.

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

vectestará na pilha, seus itens (ponteiros para Type) estarão na pilha e você não pode dizer onde serão Typeos pontos apontados pelos ponteiros. Pode estar na pilha, pode estar na pilha, pode estar nos dados globais, pode estar em lugar nenhum (isto é, NULLponteiros).

Aliás, a implementação pode de fato armazenar alguns vetores (geralmente de tamanho pequeno) na pilha completamente. Não que eu conheça alguma dessas implementações, mas pode.

jpalecek
fonte
23

Supondo que uma implementação que realmente tenha uma pilha e uma pilha (C ++ padrão não exija a exigência de tais coisas), a única declaração verdadeira é a última.

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

Isso é verdade, exceto a última parte ( Typenão estará na pilha). 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);
  }

Da mesma forma:

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

True, exceto a última parte, com um exemplo de contador semelhante:

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

Para:

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

isso é verdade, mas observe aqui que os Type*ponteiros estarão na pilha, mas as Typeinstâncias para as quais eles apontam não precisam ser:

  int main() {
    vector<Type*> bar;
    Type foo;
    bar.push_back(&foo);
  }
Flexo
fonte
em que tipo de contexto você não teria uma pilha? Entendo que você está dizendo que o padrão não exige isso, mas na prática, quando você ficaria sem uma pilha?
Nerdtron 07/11
3
@Nerdtron - IIRC em alguns microcontroladores pequenos, você tem uma pilha de chamadas que pode armazenar nada além do PC (contador de programa) no ponto da última chamada, pronto para um RET. Seu compilador pode, portanto, optar por colocar o "armazenamento automático" (para funções não recursivas) em um local fixo com pouca / nenhuma relação com o fluxo de execução. Isso poderia sensivelmente achatar todo o programa. Mesmo no caso recursivo, você pode ter uma política de "pilha por função" ou uma pilha separada para variáveis ​​automáticas e endereços de retorno, o que torna a frase "a pilha" um tanto sem sentido.
Flexo
Você pode usar a alocação baseada em heap para tudo e ter uma "pilha de limpeza" que gerencia o armazenamento automático (e possivelmente deletetambém).
Flexo
3

Somente esta afirmação é verdadeira:

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

Type* ponteiros são alocados na pilha, porque a quantidade de ponteiros pode mudar dinamicamente.

vect nesse caso, é alocado na pilha, porque você a definiu como uma variável de pilha local.

Alexei Khlebnikov
fonte
2
Type * não indica alocação de heap, simplesmente um ponteiro para um objeto Type. Dito isto, o vetor armazena o ponteiro na pilha. int a = 5; int * ptr_to_a = & a; vetor <int *> vec; vec.push_back (ptr_to_a); (ver resposta de jpalecek)
Matthew Russell
1

vector tem um interno allocatorque é responsável por alocar / desalocar memórias de heappara o vector element. Portanto, não importa como você crie um vetor, ele elementsempre será alocado no heap. Quanto aos metadados do vetor, isso depende da maneira como você os cria.

Bingo
fonte