logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog

follow us in feedly

Tutorial de STL, parte 2: Containers

Containers são objetos que contém outros objetos, como listas, pilhas, filas, etc. Os suporte a containers é um dos pilares da STL.

O primeiro container que veremos - e também o mais simples - é o vector. Ele funciona de forma muito parecida com a array comum do C, com algumas diferenças básicas: o gerenciamento de memória é automático, seu tamanho pode ser modificado durante o tempo de execução, e quando você passa um std::vector como parâmetro a informação de tamanho não se perde. Isso sem contar as facilidades...

Como um trecho de código vale mais do que uma porta de avião caindo, vamos a ele:


#include <iostream>
#include <vector>
#include <assert.h>
 
using std::cout;
using std::endl;
 
int main(int argc, char* argv[])
{
  std::vector<int> v1(10);
  std::vector<int> v2;

 
  cout << "tamanho inicial de v1:" << v1.size() << endl;
  cout << "tamanho inicial de v2:" << v2.size() << endl;

 
  cout << "um item de v1" << v1[5] << endl;
 
  for(int a = 0 ; a < 10 ; a++)
    v2.push_back(a);

  cout << "novo tamanho de v2:" << v2.size() << endl;
 
  // exclui o último item do vector, reduzindo seu tamanho em 1
  v1.pop_back();

  cout << "um item de não existente em v2:" << v2[15] << endl;
 
  // a memória é contígua, como no array
  assert(&v2[5] - &v2[4] == 1);
  assert(((char*)&v2[5]) - ((char*)&v2[4]) == sizeof(int));
 

 
  return 0;
}

Algumas coisas merecem explicações, vamos à elas. O vetor v1 foi alocado da mesma forma que um array C, só que como ele é um objeto o tamanho é passado no construtor. A diferença mais notória entre o array e o vector é que os valores do vector são inicializados com zero. Na realidade, o que acontece é que o objetos criados no vector, são inicializados usando o seu construtor default. E o construtor default do tipo int inicializa a variável com 0. Um exemplo é o seguinte trecho de código:


  int x = int();
  std::cout << x << std::endl

O código acima mostra que a variável x tem valor 0.

Outra coisa notória é que, da mesma forma que um array C, é possível acessar um item com índice maior do que o tamanho do vector, usando o operador []. No código de exemplo eu acesso o item 15 de um vector que tem tamanho 10, e isso não gera exceção (mas, é claro, gera problemas). Nenhum container STL faz verificação de limite de tamanho usando o operador [], cabe ao programador verificar isso antes do acesso. Isso funciona dessa forma para que o acesso aos containers STL fique (quase) tão rápido quanto o acesso a um array. Filosofia C++: você só paga por aquilo que você usa. Caso você queira verificação de tamanho durante o acesso, o vector provê o método at(), que dispara um exceção caso o índice esteja além dos limites do container.

O método push_back(), encontrado em vários containers, adiciona um item no final do container, aumentando o seu tamanho em um item. Após o loop do código acima, o método size() do container retornará 10. Da mesma forma, o método pop_back() exclui o último item do array, reduzindo seu tamanho em 1.

Cada container STL tem suas característica particulares, e as do vector são basicamente:

  • suporte a acesso linear e aleatório dos elementos;
  • tempo constante para inserção e remoção de elementos no final do container;

Para mais informações veja a Referência do std::vector no site da SGI.


Em 16/08/2006 23:51, por Rodrigo Strauss


  
 
 
Comentários
Wanderley Caloni | website | e-mail | em 17/08/2006 | #
Ao mesmo tempo que a classe vector da STL mantém a filosofia da perfomance, ela fornece um método mais seguro, o "at", que faz a mesma coisa que o operador de subscrito, porém verifica se o índice passado não está fora do limite de dados. Caso esteja fora, lança a exceção out_of_range:

std::vector<int> v(5);

for( int i = 0; i < 10; ++i )
{
try
{
std::cout << v[i] << endl;
}
catch(std::out_of_range& e)
{
cout << "Ops!" << endl;
break;
}
}
Rodrigo Strauss | website | em 17/08/2006 | #
Valeu, corrigido. Só que no seu exemplo de código você esqueceu e usou o operador [] ao invés do at() :-)
Wanderley Caloni | website | e-mail | em 18/08/2006 | #
Ehehehheheheh foi pra ver se estava esperto =P

Também temos que considerar que o código acima está naquela licença em que eu não me responsabilizo por quaisquer problemas que você venha a ter ao utilizá-lo =)

[]s
Andrea | em 15/09/2006 | #
Olá Rodrigo

Eu gostei muito do seu tutorial, ele já tem continuação ?
A parte 3 ? Tô aguardando.

Ate logo

Andrea
Rodrigo Strauss | website | em 15/09/2006 | #
Sim, já está no forno. :-)
Guilherme | e-mail | em 06/10/2006 | #
tem como usar o vector com uma classe?
tipo, vector<Pessoa> p...

inté.
Rodrigo Strauss | website | em 06/10/2006 | #
Sim, sem problemas.
Flavio T. Tajiri | em 23/05/2008 | #
Olá! gostei muito dos tutoriais, está de parabéns... porém estou com uma dúvida... Copiei o código da mesma forma que está descrito no tuto, ele compila normalmente mas ao executar, dá erro justamente na parte de buscar um elemento fora do vector. Usando o operador[] ele verificou o tamanho do vector e acusou o erro out_of_range, exatamente o oposto do que foi explicado. Como é possível?

Estou usando o Visual Studio 2008 Express.
Marcos V. | e-mail | em 04/02/2009 | #
Bom, eu também uso o visual C++ Exress, como você está executando o programa compilado dento do VC++ ele aponta o problema. Agora, se você for no executável e usa-lo vai receber aquela janelinha "O <executavel>.exe encontrou um problema e precisa ser fechado" ou seja, um bug. para evitar isso existe a função at().

Espero estar correto, caso contrário me corrijam. Os tutoriais estão ajudando muito, parabéns Strauss.
Guga | em 17/10/2011 | #
Rodrigo, no trecho de código abaixo vc comete um erro em tentar acessar um valor que vc ainda n adicionou, vc reservou 10 elementos pro vector mas n adicionou nada, ou seja, ele está vazio rs.

cout << "um item de v1" << v1[5] << endl;
Rodrigo Strauss | website | e-mail | em 18/10/2011 | #
Guga, o trecho está correto. Note que na declaração do vetor eu passo o número 10 no construtor. Isso inicializa o vetor com tamanho 10.

Todos os valores são inicializados dentro do vetor com o construtor padrão, o que faz com que o int fique com valor zero.
Algo a dizer?
Nome:


Site:


E-mail:


Escreva o número vinte e seis:


 Não mostre meu e-mail no site, não serve pra nada mesmo...

Comentário





Os comentários devem ser sobre assuntos relativos ao post, eu provavelmente apagarei comentários totalmente offtopic. Se quiser me enviar uma mensagem, use o formulário de contato. E não esqueça: isso é um site pessoal e eu me reservo o direito de apagar qualquer comentário ofensivo ou inapropriado.
rebarba rebarba
  ::::