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