Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Smart Pointers Ligeros

Iniciado por CoLSoN2, 09 de Enero de 2006, 12:26:32 PM

« anterior - próximo »

CoLSoN2

 Estoy pensando en comenzar a utilizar smart pointers de forma extensiva en todo lo que hago y estoy buscando alguna implementación que sea ligera (todo lo posible pese a usar reference counting) y no tenga dependencias externas (nada de los de Boost). También que sea lo más cómoda de usar (lo más cercano a trabajar directamente con punteros). Alguien me recomienda alguna? Qué tal shared_ptr de STL?

Además de eso, tengo una duda. Si tengo un método que ahora tiene un parámetro de tipo Widget*, con esta nueva forma de trabajar estaría pasando un smart_pointer&, no? Pero en este caso, como podría pasar un "puntero" de una clase derivada de Widget (polimorfismo de toda la vida, vamos)?
Manuel F. Lara
Descargar juegos indie  - blog sobre juegos indie y casual
El Desarrollo Personal.com  - blog sobre productividad, motivación y espíritu emprendedor

zupervaca

 Una implementación sencilla seria algo así:
class Pointer
{
public:
Pointer( void *pData, int nSize = 0 )
{
 this->pData = pData;
 this->nSize = nSize;
 nCount = 1;
}

inline void AddRef()
{
 nCount++;
}

inline void Release()
{
 if( nCount == 1 )
 {
  delete pData;
 }
 else
 {
 nCount--;
 }
}

inline int GetDataSize()
{
 return nSize;
}

inline void *GetData()
{
 return pData;
}

inline int GetCountRefs()
{
 return nCount;
}

~Pointer()
{
Release();
}

private:
void *pData;
int nSize, nCount;
};

En vez de void podrías adaptarlo a usarlo con templates, aunque este estilo de implementación es muy sencillo y tal vez se te quede corto antes de usarlo :lol: .

CoLSoN2

Cita de: "zupervaca"aunque este estilo de implementación es muy sencillo y tal vez se te quede corto antes de usarlo :lol: .
Exacto, me refería a una implementación sencilla *pero* totalmente funcional.
Manuel F. Lara
Descargar juegos indie  - blog sobre juegos indie y casual
El Desarrollo Personal.com  - blog sobre productividad, motivación y espíritu emprendedor

_XUTI_H_

 ¿Has probado los Smart Pointers que gasta el tipo que diseño el Enginuity?

Este es el link de la segunda parte del articulo de GameDev.net donde aparece el código de los CMMPointers y creo que también algo del sistema de gestión de memoria.

Yo creo que funcionan bastante bien, pero no és una implementación demasiado "ligera" :P

Salu2
UTI

AK47

 Estoo... he mirado las MSDN y no me sale el shared_ptr. ¿Es de las STL? ¿No te estarías refiriendo al auto_ptr?

CoLSoN2

 
Cita de: "AK47"Estoo... he mirado las MSDN y no me sale el shared_ptr. ¿Es de las STL? ¿No te estarías refiriendo al auto_ptr?
Sí, fallo mío, shared_ptr es de Boost.
Manuel F. Lara
Descargar juegos indie  - blog sobre juegos indie y casual
El Desarrollo Personal.com  - blog sobre productividad, motivación y espíritu emprendedor

Marci

 Si no encuentras nada hecho puedes echarle un ojo al libro "The Art of C++". Dedica un capitulo a crear un "Simple Garbage Collector for C++" (sin usar auto_ptr) . El libro desarrolla  la clase template class GCPtr para el manejo de los punteros.

CitarGCPtr is the heart of the garbage collector. It implements a new pointer type that keeps a reference count for objects allocated on the heap. It also provides the garbage collection functionality that recycles unused memory

ethernet

 Creo que colson lo que quiere es C++ con ref count porque ha visto python y se ha dado cuenta de que es un lujazo no tener que preocuparte por punteros a 0.

La razón de no usar boost es por evitar sobrecargar?

seryu

 Si no quieres boost, la otra famosa es la de Loki:

http://sourceforge.net/projects/loki-lib/john

En el libro Modern C++ Design la explican y hay un monton de información útil.

Si realmente pasas de estos tochos, igual te interesa esta:

http://yasper.sourceforge.net/

Flint

 Bueno, ya te han dado montones de recursos, pero por si acaso, ésta es la implementación del smart pointer en el motor Wild Magic de David Eberly:

Wm3SmartPointer.h
// Geometric Tools, Inc.
// http://www.geometrictools.com
// Copyright (c) 1998-2006.  All Rights Reserved
//
// The Wild Magic Library (WM3) source code is supplied under the terms of
// the license agreement
//     http://www.geometrictools.com/License/WildMagic3License.pdf
// and may not be copied or disclosed except in accordance with the terms
// of that agreement.

#ifndef WM3SMARTPOINTER_H
#define WM3SMARTPOINTER_H

#include "Wm3FoundationLIB.h"
#include "Wm3System.h"

namespace Wm3
{

template <class T>
class Pointer
{
public:
   // construction and destruction
   Pointer (T* pkObject = 0);
   Pointer (const Pointer& rkPointer);
   ~Pointer ();

   // implicit conversions
   operator T* () const;
   T& operator* () const;
   T* operator-> () const;

   // assignment
   Pointer& operator= (T* pkObject);
   Pointer& operator= (const Pointer& rkReference);

   // comparisons
   bool operator== (T* pkObject) const;
   bool operator!= (T* pkObject) const;
   bool operator== (const Pointer& rkReference) const;
   bool operator!= (const Pointer& rkReference) const;

protected:
   // the shared object
   T* m_pkObject;
};

#include "Wm3SmartPointer.inl"

}

#endif




Wm3SmartPointer.inl
// Geometric Tools, Inc.
// http://www.geometrictools.com
// Copyright (c) 1998-2006.  All Rights Reserved
//
// The Wild Magic Library (WM3) source code is supplied under the terms of
// the license agreement
//     http://www.geometrictools.com/License/WildMagic3License.pdf
// and may not be copied or disclosed except in accordance with the terms
// of that agreement.

//----------------------------------------------------------------------------
template <class T>
Pointer<T>::Pointer (T* pkObject)
{
   m_pkObject = pkObject;
   if (m_pkObject)
   {
       m_pkObject->IncrementReferences();
   }
}
//----------------------------------------------------------------------------
template <class T>
Pointer<T>::Pointer (const Pointer& rkPointer)
{
   m_pkObject = rkPointer.m_pkObject;
   if (m_pkObject)
   {
       m_pkObject->IncrementReferences();
   }
}
//----------------------------------------------------------------------------
template <class T>
Pointer<T>::~Pointer ()
{
   if (m_pkObject)
   {
       m_pkObject->DecrementReferences();
   }
}
//----------------------------------------------------------------------------
template <class T>
Pointer<T>::operator T* () const
{
   return m_pkObject;
}
//----------------------------------------------------------------------------
template <class T>
T& Pointer<T>::operator* () const
{
   return *m_pkObject;
}
//----------------------------------------------------------------------------
template <class T>
T* Pointer<T>::operator-> () const
{
   return m_pkObject;
}
//----------------------------------------------------------------------------
template <class T>
Pointer<T>& Pointer<T>::operator= (T* pkObject)
{
   if (m_pkObject != pkObject)
   {
       if (pkObject)
       {
           pkObject->IncrementReferences();
       }

       if (m_pkObject)
       {
           m_pkObject->DecrementReferences();
       }

       m_pkObject = pkObject;
   }
   return *this;
}
//----------------------------------------------------------------------------
template <class T>
Pointer<T>& Pointer<T>::operator= (const Pointer& rkPointer)
{
   if (m_pkObject != rkPointer.m_pkObject)
   {
       if (rkPointer.m_pkObject)
       {
           rkPointer.m_pkObject->IncrementReferences();
       }

       if (m_pkObject)
       {
           m_pkObject->DecrementReferences();
       }

       m_pkObject = rkPointer.m_pkObject;
   }
   return *this;
}
//----------------------------------------------------------------------------
template <class T>
bool Pointer<T>::operator== (T* pkObject) const
{
   return (m_pkObject == pkObject);
}
//----------------------------------------------------------------------------
template <class T>
bool Pointer<T>::operator!= (T* pkObject) const
{
   return (m_pkObject != pkObject);
}
//----------------------------------------------------------------------------
template <class T>
bool Pointer<T>::operator== (const Pointer& rkPointer) const
{
   return (m_pkObject == rkPointer.m_pkObject);
}
//----------------------------------------------------------------------------
template <class T>
bool Pointer<T>::operator!= (const Pointer& rkPointer) const
{
   return (m_pkObject != rkPointer.m_pkObject);
}
//-----------------------------------------

josette

   Esto de los auto_pointers que funcion tiene exactamente, para que sirven?
Seria recomdable usarlos? o solo hay que usarlos en ciertos casos?

Sacrifai

 
Cita de: "josette"Esto de los auto_pointers que funcion tiene exactamente, para que sirven?
Seria recomdable usarlos? o solo hay que usarlos en ciertos casos?
No me hagas mucho caso porque yo el tema este "ni papa". El auto_ptr es un puntero que se elimina solo y creo que tambien, puede cambiar el tipo de objeto al que apunta en tiempo de ejecución ( corregidme si me equivoco ).

AK47

 Básicamente simplifica la gestión de memoria:

void jarl()
{
 Bullet *pBullet = new Bullet;
}
// Memory leak!

Su version auto_ptr-ril:

void jarl()
{
 std::auto_ptr<Bullet> pBullet;
 pBullet.reset(new Bullet);
}
// pBullet es liberado automáticamente


Obviamente esto es un ejemplo sencillo. Puedes usar auto_ptr como variable miembro de una clase, por ejemplo. Así, al destruirse un objeto de esa clase, el auto_ptr dará buena cuenta de su puntero (vamos, que le hará un delete :P)

josette

 Ok, lo pillo. Pero no siempre que se use un puntero ha de usarse el auto_ptr, porque no siempre interesa que se borre.

  Si bien lo comprendo, el auto_ptr es para gestionar recursos de forma que cuando un objeto se va a cargar un recurso si ya esta cargado pues se incrementa el contador y si no lo esta pues se carga. Y conforme los objetos que usan el recurso se van eliminando cuando se vaya a eliminar el ultimo pues se libera el recurso.

editado:
  Tb es verdad que a veces hay objetos que interesa que se creen admitiendo parametros que se saben en tiempo de ejecucion y por tanto se ha de declarar como punteros, aunque teoricamente deberían ser Objetos. Por ejemplo:

class Cgame
{
  Cplayer m_Player;
}

si Player se tubiera que crear con parametros entonces

class Cgame
{
Cplayer* m_player;
 init(...,...,...){ m_player = new Cplayer(...);
}

y luego hay que destruirlo;

Pues se usa auto_ptr y asi el player se destruye el solo cuando se destruya Cgame.


class Cgame
{
 auto_ptr m_Ptr_player;
 init(...,...,...){ Ptr_player.reset(new Cplayer(...));
}

aunque donde hay un buen programador hay un buen destrutor!!! ;)  






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.