Rodrigo Strauss :: Blog
![]() |
Follow @rodrigostrauss |
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
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;
}
}