If you simply return an internal pointer, you must consider that the caller can retain and use this pointer for an arbitrarily long time.
const--the caller can modify the object (though the latter possibility isn't acceptable at Taligent).
constpointers, as it gives you a chance to synthesize the subobject if you don't want it around all the time (you can delete the synthesized object at the DoneWithObject call). Of course, this only works for one client at a time.
Even better is to use the lifetime of a lightweight object to bound the access to the subobject, rather than explicit UseObject and DoneWithObject calls.
The best approach is not to return pointers to subobjects. Instead, use lightweight surrogate objects to set and get subobjects by value, and to obviate the need for pointers. This technique also works with concurrency. For more on this technique, see "Surrogate objects" on page 121.