I have few questions on the best practices of using shared_ptr.
Question 1
Is copying shared_ptr cheap? Or do I need to pass it as reference to my own helper functions and return as value? Something like,
void init_fields(boost::shared_ptr<foo>& /*p_foo*/);
void init_other_fields(boost::shared_ptr<foo>& /*p_foo*/);
boost::shared_ptr<foo> create_foo()
{
    boost::shared_ptr<foo> p_foo(new foo);
    init_fields(p_foo);
    init_other_fields(p_foo);
}
Question 2
Should I use boost::make_shared to construct a shared_ptr? If yes, what advantages it offers? And how can we use make_shared when T doesn't have a parameter-less constructor?
Question 3
How to use const foo*? I have found two approaches for doing this.
void take_const_foo(const foo* pfoo)
{
}
int main()
{
    boost::shared_ptr<foo> pfoo(new foo);
    take_const_foo(pfoo.get());
    return 0;
}
OR
typedef boost::shared_ptr<foo> p_foo;
typedef const boost::shared_ptr<const foo> const_p_foo;
void take_const_foo(const_p_foo pfoo)
{
}
int main()
{
     boost::shared_ptr<foo> pfoo(new foo);
     take_const_foo(pfoo);
     return 0;
}
Question 4
How can I return and check for NULL on a shared_ptr object? Is it something like,
boost::shared_ptr<foo> get_foo()
{
     boost::shared_ptr<foo> null_foo;
     return null_foo;
}
int main()
{
     boost::shared_ptr<foo> f = get_foo();
     if(f == NULL)
     {
          /* .. */
     }
     return 0;
}
Any help would be great.