Diz a lenda que o seguinte código dá um erro em tempo de execução:
#include <cstring>
class Foo
{
public:
Foo ( int size ) :
mSize(size),
mValues( new char[mSize] )
{
memset( mValues, 0, mSize );
}
~Foo ()
{
delete[] mValues;
}
private:
char* mValues;
const int mSize;
};
int main()
{
Foo deu(10);
return 0;
}
Você sabe dizer qual é?
O problema aqui está na alocação de memória para mValues. Observe o construtor:
Foo ( int size ) :
mSize(size),
mValues( new char[mSize] )
{
memset( mValues, 0, mSize );
}
Aparentemente está ok, não é? No exemplo acima, o objeto é criado passando 10 como parâmetro. Sendo assim, o valor 10 é atribuído para mSize, e depois mValues é alocado com o tamanho de mSize, e então é feito um memset para zerar todos os valores de mValues.
Muito bonito, mas o problema está na ordem de inicialização das variáveis. Quem define esta ordem é a ordem em que as variáveis foram declaradas dentro da classe.
Note:
private:
char* mValues;
const int mSize;
Não importa se você vai chamar
Foo ( int size ) :
mSize(size),
mValues( new char[mSize] )
{
...
}
ou
Foo ( int size ) :
mValues( new char[mSize] ),
mSize(size)
{
...
}
que mValues sempre vai ser inicializado antes de mSize.
Para resolver o problema?
Inverta a ordem de declaração das variáveis.
O seguinte código:
#include <cstring>
class Foo
{
public:
Foo ( int size ) :
mSize(size),
mValues( new char[mSize] )
{
memset( mValues, 0, mSize );
}
~Foo ()
{
delete[] mValues;
}
private:
const int mSize;
char* mValues;
};
int main()
{
Foo deu(10);
return 0;
}
Não apresenta problema algum.
Dizem que é uma boa prática inicializar as variáveis no construtor na mesma ordem que elas foram declaradas na classe para evitar este tipo de dúvida. Se você tiver paciência para fazê-lo, mande bala! :)