There is some disagreement in my team about pointer container usage for a particular context. Please consider:
int main() {
// Top level. This is an important fact to the context
// i.e. that the following instance is at this level
// so that its members are essentially at program scope.
MainClass mainClass;
mainClass.run();
}
// A instance of a class derived from Buffer does something very complex
// (it has various handles to resources/allocated memory) so that you would
// never want to copy an instance.
class Buffer;
class MainClass {
#make_decision_here_based_on_stack_overflow_responses
shared_ptr<Buffer> buffer; // 1
scoped_ptr<Buffer> buffer; // 2
#end_decision
MainClass() {
// non-trivial initialisation of buffer with any of a number of derived classes:
buffer.reset( ... )
}
void run() {
#make_decision_here_based_on_stack_overflow_responses
SomeSubservientClass sub(*buffer); // a
SomeSubservientClass sub(buffer.get()); // b
SomeSubservientClass sub(buffer); // c
#end_decision
sub.do_stuff()
}
};
(I hope you can understand the special preprocessor code here that does not actually exist but would be nice if it did :)
The code we have is currently have is in state "1b" (shared_ptr member, pass down bare ptr) but we think this is not how it should be. I'd be interested to know what anyone thinks at first glance would be the most natural/reasonable and safest thing to do and justification. Or if anyone wants to suggest a "3" or a "d". I have an opinion myself but don't want to share it yet.
Choice of smart pointer is a choice of ownership strategy. You have to ask yourself this question:
MainClass
the sole owner of the Buffer
instance? Or does it make sense for the Buffer
instance stored in MainClass
to outlive the MainClass
object? (Or would it make sense if MainClass
became a component of a larger system and lost its application-lifetime status?)If the answer is makes sense, go with a shared pointer. If the answer is sole owner/doesn't make sense, use something that expresses unique ownership - scoped_ptr
(or std::unique_ptr
, if available).
If you end up with unique ownership, use option 'a' for passing the object along. A function should only ever take a pointer parameter if the null pointer is a valid input for it.
If you end up with shared ownership, there are two possible situations. For passing the buffer to places which share the ownership, pass the shared_ptr
itself. For passing it to places which just observe/modify, use 'a' as above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With