paulo1205
(usa Ubuntu)
Enviado em 11/04/2013 - 17:39h
Seu código tem uma quantidade razoável de bugs, a saber:
1) Na primeira chamada a
calloc (), você errou o tipo passado ao operador
sizeof : deveria ter sido
int* , não
int .
2) Caso ocorra um erro na alocação das colunas em cada linha, você deveria desalocar as linhas anteriores já alocadas e também o mapa antes de lançar a exceção.
3) Na chamada que faz a
memset (), você faz algo muito perigoso ao assumir que as colunas de cada linha vão ficar em posições de memória contíguas. Para alocação dinãmica na forma como você fez, provavelmente não será verdade. (EDIT: Aliás, o tamanho usado nesse
memset () é idêntico a
sizeof(int) . Você provavelmente quis dizer -- ainda erroneamente --
sizeof(int)*this->altura*this->largura , não?)
4) Chamar
calloc (), que gasta tempo preenchendo a memória alocada com zeros, para depois chamar
memset () com outro valor é, mesmo que não tivesse o bug relatado acima, desperdício. Teria sido melhor, nesse caso, ter usado
malloc (), que só aloca a área, mas não se preocupa de preecnhê-la com valor algum.
--------
Já que está usando C++, por que não usa
std::vector ? Você poderia declarar o membro
mapa com
std::vector< std::vector<int> > mapa;
e fazer a inicialização, dentro do contrutor da sua classe, do seguinte modo.
mapa.resize(altura, std::vector<int>(largura, NADA));
Só uma linha já lhe dá a alocação de todos os elementos e os preenche com um valor inicial. Se ocorrer uma falha de alocação a qualquer momento, você não precisa de se preocupar em testá-la manualmente, nem com desalocar os dados parcialmente alocados. Você não vai sequer precisar de colocar desalocação explicitamente no destrutor.
Leia sobre
std::vector .
--------
Se você quiser mesmo, com fins didáticos (ou por masoquismo), usar arrays nativos e alocação dinâmica explícita, é geralmente mais conveniente e recomendável usar o operador nativo
new[] do que
calloc () ou
malloc (), pois o compilador já lhe daria certezas quanto ao tipo do dado alocado, sem o risco de cometer o primeiro dos erros que eu indiquei acima.
O código abaixo tenta corrigir todos os bugs, usando a forma C++ de alocação dinâmica. Veja como, apesar de inchado para tratar o segundo bug, o código com
new[] ficaria mais "limpo" por dispensar aqueles casts supérfluos e não ter necessidade de
if s para testar se cada alocação foi ou não bem sucedida para, dependendo do caso, lançar manualmente uma exceção.
Mapa::Mapa() { // construtor
// inicializa primeiro os elementos que nao dependam de mapa.
// bla bla bla...
// mapa deve ter sido declarado como "int **mapa;"
mapa=new int*[altura];
int i=0;
try {
for(; i<altura; i++){
mapa[i]=new int[largura];
fill(mapa[i], mapa[i]+largura, NADA); // fill() fica dentro de <algorithm>
}
}
catch(std::bad_alloc &e){
while(i>0)
delete [] mapa[--i];
delete [] mapa;
throw; // re-dispara a excecao recebida
}
// Continua inicilizacao do objeto no construtor, especialmente
// com coisas contidas no mapa, que agora esta incializado.
// blu blu blu...
}
Não se pode esquecer de colocar o código análogo no destrutor.
Mapa::~Mapa() {
// Desconstroi o que depende do mapa.
// bla bla bla...
// Desconstroi o mapa
for(int i=altura; i>0; )
delete [] mapa[--i];
delete [] mapa;
// Desconstroi o que nao depende do mapa.
// blu blu blu...
}