Любое преимущество использования shared_ptr перед scoped_ptr на верхнем уровне?
В моей команде есть некоторые разногласия по поводу использования контейнера указателя для определенного контекста. Пожалуйста примите к сведению:
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()
}
};
(Я надеюсь, что вы можете понять специальный код препроцессора, который на самом деле не существует, но было бы неплохо, если бы он был:)
Код, который у нас есть в данный момент, находится в состоянии "1b" (член shared_ptr, передайте голый ptr), но мы думаем, что это не так, как должно быть. Мне было бы интересно узнать, что на первый взгляд кто-то считает наиболее естественным / разумным и самым безопасным занятием и оправданием. Или если кто-то хочет предложить "3" или "d". Я сам имею мнение, но пока не хочу им делиться.
1 ответ
Выбор умного указателя - это выбор стратегии владения. Вы должны задать себе этот вопрос:
- Является
MainClass
единственный владелецBuffer
пример? Или это имеет смысл дляBuffer
экземпляр хранится вMainClass
пережитьMainClass
объект? (Или это будет иметь смысл, еслиMainClass
стал компонентом более крупной системы и утратил статус приложения?
Если ответ имеет смысл, используйте общий указатель. Если ответ является единственным владельцем / не имеет смысла, используйте что-то, что выражает уникальное право собственности - scoped_ptr
(или же std::unique_ptr
, если доступно).
Если вы получаете уникальное право собственности, используйте опцию "а" для передачи объекта. Функция должна всегда принимать параметр указателя, только если нулевой указатель является допустимым входным параметром для него.
Если вы в конечном итоге с общим владением, есть две возможные ситуации. Для передачи буфера в места, которые разделяют владение, передайте shared_ptr
сам. Для передачи его в места, которые просто наблюдают / изменяют, используйте "a", как указано выше.