make_shared - shared_ptr c++
Puntero NULL con boost:: shared_ptr? (6)
¿Cuál es el equivalente a lo siguiente?
std::vector<Foo*> vec;
vec.push_back(NULL);
cuando se trata de boost::shared_ptr
? ¿Es el siguiente código?
std::vector< boost::shared_ptr<Foo> > vec;
vec.push_back(boost::shared_ptr<Foo>());
Nota: puedo rechazar muchos de esos objetos. ¿Debo declarar un objeto static nullPtr
global en nullPtr
parte? De esta forma, solo uno de ellos debería construirse:
boost::shared_ptr<Foo> nullPtr;
Aquí hay algo que creo que es un poco más simple y funciona bien
(recuerda que typedef
es tu amigo):
#include <cstdlib>
#include <vector>
#include <iostream>
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr< std::vector<char> > CharVecHandle;
inline CharVecHandle newCharVec(std::vector<char>::size_type size) {
return CharVecHandle(new std::vector<char>(size));
}
inline CharVecHandle newCharVec(void) {
return CharVecHandle();
}
int main ( void )
{
CharVecHandle cvh = newCharVec();
if (cvh == NULL)
std::cout << "It''s NULL" << std::endl;
else
std::cout << "It''s not NULL" << std::endl;
std::vector< CharVecHandle > cvh_vec;
cvh_vec.push_back(newCharVec(64));
cvh_vec.push_back(newCharVec());
// or call the NULL constructor directly
cvh_vec.push_back(CharVecHandle());
return EXIT_SUCCESS;
}
Bueno, esto es legal:
shared_ptr<Foo> foo; /* don''t assign */
Y en este estado, no apunta a nada. Incluso puedes probar esta propiedad:
if (foo) {
// it points to something
} else {
// no it doesn''t
}
Entonces, ¿por qué no hacer esto?
std::vector < shared_ptr<Foo> > vec;
vec.push_back (shared_ptr<Foo>); // push an unassigned one
En C ++ 0x, puede simplemente convertir de nullptr
a std::shared_ptr
:
std::vector< boost::shared_ptr<Foo> > vec;
vec.push_back(nullptr);
Podría declarar un nullPtr
global para shared_ptr<Foo>
. Pero si contaminas el espacio de nombre global, ¿cómo llamarías al nullPtr
global para shared_ptr<Bar>
?
Normalmente, declaro ptr nulo como estático en la clase del puntero.
#include <boost/shared_ptr.hpp>
class Foo; // forward decl
typedef boost::shared_ptr<Foo> FooPtr;
class Foo
{
public:
static FooPtr Null;
}
...
// define static in cpp file
FooPtr Foo::Null;
...
// use Foo Null
vec.push_back(Foo::Null);
De esta forma, cada clase tiene un nulo estático.
Sí, declare un puntero nulo estático global.
Su sugerencia (llamar al shared_ptr<T>
sin argumentos) es correcta. (Llamar al constructor con el valor 0 es equivalente). No creo que esto sea más lento que llamar a vec.push_back()
con un shared_ptr<T>
preexistente, ya que se requiere una construcción en ambos casos (ya sea directa construcción o copia-construcción).
Pero si quieres una sintaxis "más agradable", puedes probar el siguiente código:
class {
public:
template<typename T>
operator shared_ptr<T>() { return shared_ptr<T>(); }
} nullPtr;
Esto declara un solo objeto global nullPtr
, que habilita la siguiente sintaxis natural:
shared_ptr<int> pi(new int(42));
shared_ptr<SomeArbitraryType> psat(new SomeArbitraryType("foonly"));
...
pi = nullPtr;
psat = nullPtr;
Tenga en cuenta que si usa esto en varias unidades de traducción (archivos fuente), tendrá que dar un nombre a la clase (por ejemplo _shared_null_ptr_type
), mover la definición del objeto nullPtr
a un archivo .cpp separado y agregar declaraciones extern
en el archivo de encabezado donde se define la clase.