Quel est l'équivalent de ce qui suit:
std::vector<Foo*> vec;
vec.Push_back(NULL);
lorsqu'il s'agit de boost::shared_ptr
? Est-ce le code suivant?
std::vector< boost::shared_ptr<Foo> > vec;
vec.Push_back(boost::shared_ptr<Foo>());
Remarque: je peux repousser beaucoup de ces objets. Dois-je déclarer un objet statique global nullPtr
quelque part? Ainsi, un seul d'entre eux devrait être construit:
boost::shared_ptr<Foo> nullPtr;
Votre suggestion (appeler le constructeur shared_ptr<T>
sans argument) est correcte. (Appeler le constructeur avec la valeur 0 équivaut.) Je ne pense pas que cela serait plus lent que d'appeler vec.Push_back()
avec un shared_ptr<T>
pré-existant, car une construction est requise dans les deux cas (construction directe ou copie).
Mais si vous voulez une syntaxe "plus agréable", vous pouvez essayer le code suivant:
class {
public:
template<typename T>
operator shared_ptr<T>() { return shared_ptr<T>(); }
} nullPtr;
Cela déclare un objet global unique nullPtr
, qui active la syntaxe naturelle suivante:
shared_ptr<int> pi(new int(42));
shared_ptr<SomeArbitraryType> psat(new SomeArbitraryType("foonly"));
...
pi = nullPtr;
psat = nullPtr;
Notez que si vous l'utilisez dans plusieurs unités de traduction (fichiers source), vous devez attribuer un nom à la classe (par exemple, _shared_null_ptr_type
), déplacer la définition de l'objet nullPtr
dans un fichier .cpp distinct, puis ajouter des déclarations extern
dans la fichier d'en-tête où la classe est définie.
Eh bien, c'est légal:
shared_ptr<Foo> foo; /* don't assign */
Et dans cet état, cela ne pointe rien. Vous pouvez même tester cette propriété:
if (foo) {
// it points to something
} else {
// no it doesn't
}
Alors pourquoi ne pas faire ceci:
std::vector < shared_ptr<Foo> > vec;
vec.Push_back (shared_ptr<Foo>); // Push an unassigned one
En C++ 0x, vous pouvez simplement convertir de nullptr
à std::shared_ptr
:
std::vector< boost::shared_ptr<Foo> > vec;
vec.Push_back(nullptr);
Vous pouvez déclarer une variable nullPtr
globale pour shared_ptr<Foo>
. Mais si vous polluez l'espace de noms global, comment appelleriez-vous la variable globale nullPtr
pour shared_ptr<Bar>
?
En règle générale, je déclare le ptr null en tant que statique dans la classe du pointeur.
#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 cette façon, chaque classe a un null statique.
Voici quelque chose que je pense est un peu plus simple et fonctionne très bien
(rappelez-vous que typedef
est votre ami):
#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;
}
Oui, déclarez un pointeur null statique global.