Rodrigo Strauss :: Blog
C++ com sanidade: resolvendo o bug usando Boost
Seguindo a série de possíveis correções para o bug da cópia de um objeto que contém um ponteiro, sugiro agora a correção que eu acho mais fácil e apropriada: usar o shared_ptr do Boost. Essa proposta segue a filosofia C++: fazer tudo com o máximo de simplicidade e reusando as bibliotecas existentes ao máximo.
Para quem não conhece, o Boost é um conjunto de bibliotecas (a maioria de templates) para C++, que é vista pelos usuários como um extensão da biblioteca padrão (namespace std). Essas bibliotecas vão de smart pointers à regular expression, de algoritmos para manipulação de strings à templates metaprogramming. Algumas das bibliotecas do Boost (acho que 10) serão adicionadas ao próximo padrão C++, nomeado provisóriamente como C++0x (0x será o ano de publicação, o último padrão é o C++98).
Como todos já sabem, um trecho de código sempre vale mais do que 100.000.000.000 palavras:
#include <iostream>
#include <boostshared_ptr.hpp>
//
// costumes Win32...
//
#ifndef DWORD
#define DWORD unsigned int
#endif
class CTest1
{
public:
CTest1() : dwValue(0)
{}
~CTest1()
{
// só para termos certeza do que está acontecendo...
std::cout << "CTest1::~CTest1() | " << (void*)this << std::endl;
}
DWORD dwValue;
std::string strValue;
};
class CTest2
{
private:
//
// transformando o ponteiro em um shared_ptr resolve o bug
//
boost::shared_ptr<CTest1> m_pTest1;
public:
CTest2()
: m_pTest1(new CTest1)
{}
//
// Não preciso um destrutor para desalocar o ponteiro.
// E nem precisei usar um linguagem mais limitada ou uma runtime lenta
//
CTest2(DWORD dw, const std::string& str)
: m_pTest1(new CTest1)
{
m_pTest1->dwValue = dw;
m_pTest1->strValue = str;
}
~CTest2()
{
std::cout << "CTest2::~CTest2() | " << (void*)this << std::endl;
}
//
// essa versão é a mais recomendada
//
const boost::shared_ptr<CTest1>& GetTest1()
{
return m_pTest1;
}
//
// vamos renomear. Eu poderia passar o ponteiro diretamente,
// mas prefiro seguir as regras de ownership do shared_ptr
// Isso chama-se "safe programming", mais do que possível em C++
//
CTest1* GetTest1_old() const
{
return m_pTest1.get();
}
};
int main(int argc, char* argv[])
{
std::vector<boost::shared_ptr<CTest2> > vecTest2;
boost::shared_ptr<CTest2> t1(new CTest2), t2(new CTest2(100,"putz grila"));
//
// agora nossas variáveis são ponteiros
//
t1->GetTest1()->dwValue = 50;
t1->GetTest1()->strValue = "baba";
//
// vamos criar um objeto e fazer uma cópia
// do CONTEÚDO de um dos ponteiros
//
CTest2 tv3 = *t1;
//
// chamando operator=, copiando o valor
//
*t2 = tv3;
//
// vamos atribuir um ponteiro ao outro.
// Note que como usamos um shared_ptr, o conteúdo do ponteiro t1 será
// automaticamente liberado, e não haverá leak
// "olhe mamãe, sem o garbage collector"
//
t1 = t2;
//
// vamos colocar um t1 no vetor. Isso coloca o ponteiro,
// e não faz cópia do objeto
//
vecTest2.push_back(t1);
//
// vamos colocar t2, que é o mesmo ponteiro de t1
//
vecTest2.push_back(t2);
BOOST_ASSERT(t1 == t2);
BOOST_ASSERT(t1.get() == t2.get());
BOOST_ASSERT(vecTest2[0] == vecTest2[1]);
//
// agora vamos pegá-lo e ver o seu valor
//
std::cout << "dwValue = " << vecTest2[0]->GetTest1()->dwValue << std::endl;
std::cout << "strValue = " << vecTest2[0]->GetTest1()->strValue << std::endl;
return 0;
}
Outros post da série:
Tinha um bug no caminho, no caminho tinha um bug
Por que o bug?
Resolvendo o bug usando um smart pointer feito em casa
Em 06/06/2005 13:11, por Rodrigo Strauss




