Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any advantage to using shared_ptr over scoped_ptr at top level?

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.

like image 900
Benedict Avatar asked Mar 23 '23 23:03

Benedict


1 Answers

Choice of smart pointer is a choice of ownership strategy. You have to ask yourself this question:

  • Is 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.

like image 112
Angew is no longer proud of SO Avatar answered Apr 30 '23 02:04

Angew is no longer proud of SO