NULL pointer with boost::shared_ptr?

Solution 1:

Your suggestion (calling the shared_ptr<T> constructor with no argument) is correct. (Calling the constructor with the value 0 is equivalent.) I don't think that this would be any slower than calling vec.push_back() with a pre-existing shared_ptr<T>, since construction is required in both cases (either direct construction or copy-construction).

But if you want "nicer" syntax, you could try the following code:

class {
public:
    template<typename T>
    operator shared_ptr<T>() { return shared_ptr<T>(); }
} nullPtr;

This declares a single global object nullPtr, which enables the following natural syntax:

shared_ptr<int> pi(new int(42));
shared_ptr<SomeArbitraryType> psat(new SomeArbitraryType("foonly"));

...

pi = nullPtr;
psat = nullPtr;

Note that if you use this in multiple translation units (source files), you'll need to give the class a name (e.g. _shared_null_ptr_type), move the definition of the nullPtr object to a separate .cpp file, and add extern declarations in the header file where the class is defined.

Solution 2:

Well, this is legal:

shared_ptr<Foo> foo;  /* don't assign */

And in this state, it doesn't point to anything. You can even test this property:

if (foo) {
    // it points to something
} else {
    // no it doesn't
}

So why not do this:

std::vector < shared_ptr<Foo> > vec;
vec.push_back (shared_ptr<Foo>);   // push an unassigned one

Solution 3:

In C++0x, you can simply convert from nullptr to std::shared_ptr:

std::vector< boost::shared_ptr<Foo> > vec;
vec.push_back(nullptr);

Solution 4:

You could declare a global nullPtr for shared_ptr<Foo>. But if you pollute the global namespace, what would you call the global nullPtr for shared_ptr<Bar>?

Typically I declare the null ptr as a static in the class of the pointer.

#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);

That way each class has a static Null.

Solution 5:

Here's something which I think is a bit simpler and works just fine

( remember that typedef is your friend ):

#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;
}