logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog

follow us in feedly

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


  
 
 
Comentários
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
  ::::