I would stay with a pointer. The link here just sends the wrong message.
You do not use object references in situations when you plan to use a pointer to an object to store and share it, etc. The main reason for C ++ references allows things like operator overloading and copying constructors to work with user-defined types. Without them, it would be difficult to provide this functionality with syntax that does not differ from built-in types.
But in this situation, you are not trying to mimic the built-in type. You work on an object that is commonly used with a pointer and even shared several different pointers. So be honest with that.
For b , which is NULL, be sure to use assert(b) (or a similar construct) to enforce the contract and terminate the invalid program. (I would not choose an exception. Even if you forget about problems with exceptions in C ++, do you plan to ever catch and handle such an exception in your code?) I would also add such statements to the whole code that m_B uses in the case of if someone forgot to call A::Initialize() .
Using a reference to ensure that the pointer is not null can skip gaps. In most implementations, you can make a reference from NULL or a dangling pointer without any errors. Your application will fail only if you try to use this link. Therefore, if someone accidentally gives you B *pb equal to NULL, you can call pa->Initialize(*pb) and nothing happens. Except pa->m_B now NULL.
Whether to use something like boost::shared_ptr up to you and your memory management strategy. This is a completely unrelated issue.
source share