Привет,
объясните, пожалуйста, как правильно/лучше делать если функции нужно только читать какие-то свойства объекта, но не нужно его менять:
class Document;
class DocumentAnalyser {
public:
virtual bool analyse(const Document* doc) const; // передавать по указателю?virtual bool analyse(const shared_ptr<Document> doc) const; // или по shared_ptr лучше?
};
shared_ptr<Document> nextDocument();
documentAnalyser->analyse(nextDocument().get()); // так?
documentAnalyser->analyse(nextDocument()); // или так?
Если приложение однопоточное, то по указателю достаточно. А если многопоточное и другой поток может удалить документ, то тогда по shared_ptr. Правильно?
МР>Если приложение однопоточное, то по указателю достаточно. А если многопоточное и другой поток может удалить документ, то тогда по shared_ptr. Правильно?
Здравствуйте, Marty, Вы писали:
M>shared_ptr разве tread safe?
А, ну да, другой поток может менять объект пока я его читаю... Ну так есть разница передавать по указателю или по shared_ptr? И вообще как правильно делать?
Здравствуйте, Максим Рогожин, Вы писали:
M>>shared_ptr разве tread safe?
МР>А, ну да, другой поток может менять объект пока я его читаю... Ну так есть разница передавать по указателю или по shared_ptr? И вообще как правильно делать?
Управление временем жизни объекта и управление его содержимым в многопоточной среде — это ортогональные вещи
Здравствуйте, Marty, Вы писали:
M>Управление временем жизни объекта и управление его содержимым в многопоточной среде — это ортогональные вещи
Я просто вижу в проекте в одних местах передается по указателю, в других по shared_ptr и хочу разобраться от чего это зависит и как надо правильно делать.
M>>Управление временем жизни объекта и управление его содержимым в многопоточной среде — это ортогональные вещи
МР>Я просто вижу в проекте в одних местах передается по указателю, в других по shared_ptr и хочу разобраться от чего это зависит и как надо правильно делать.
Здравствуйте, Максим Рогожин, Вы писали:
M>>Если нет документации — беги оттуда
МР>Т.е. общепринятого подхода в C++ к этому вопросу нет — это зависит от дизайна конкретного проекта. Так?
Здравствуйте, Максим Рогожин, Вы писали:
МР>Привет, МР>объясните, пожалуйста, как правильно/лучше делать если функции нужно только читать какие-то свойства объекта, но не нужно его менять: МР>
МР>class Document;
МР>class DocumentAnalyser {
МР>public:
МР> virtual bool analyse(const Document* doc) const; // передавать по указателю?
МР> virtual bool analyse(const shared_ptr<Document> doc) const; // или по shared_ptr лучше?
МР>};
МР>shared_ptr<Document> nextDocument();
МР>documentAnalyser->analyse(nextDocument().get()); // так?
МР>documentAnalyser->analyse(nextDocument()); // или так?
МР>
МР>Если приложение однопоточное, то по указателю достаточно. А если многопоточное и другой поток может удалить документ, то тогда по shared_ptr. Правильно?
МР>UPDATE: МР>А если nextDocument() вот так объявлена: МР>
МР>std::unique_ptr nextDocument();
МР>
МР>тогда как лучше?
Лучше по указателю, потому что сейчас у вас shared_ptr, потом unique_ptr, потом uber_mega_c++2020_ai_ptr, а указатель как был, так и останется. Дополнительно, в принимающем интерфейсе я бы заменил указатель на ссылку.
Более того, в случае со ссылкой интерфейс умного указателя становится прозрачным, потому что для доступа с содержимому используется не .get() или что-то ещё, а de-reference syntax:
class Document;
class DocumentAnalyser {
public:
virtual bool analyse(const Document& doc) const;
};
any_ptr<Document> nextDocument();
documentAnalyser->analyse(*nextDocument());
Здравствуйте, mbait, Вы писали:
M>Более того, в случае со ссылкой интерфейс умного указателя становится прозрачным, потому что для доступа с содержимому используется не .get() или что-то ещё, а de-reference syntax:
В случае указателя, а не ссылки, можно использовать пару операторов &* вместо .get()
Здравствуйте, mbait, Вы писали:
M>Лучше по указателю, потому что сейчас у вас shared_ptr, потом unique_ptr, потом uber_mega_c++2020_ai_ptr, а указатель как был, так и останется. Дополнительно, в принимающем интерфейсе я бы заменил указатель на ссылку.
Суть в том, что сложные сценарии могут сделать невозможным определение ситуации "когда удалить объект по указателю". И shared_ptr как раз отвечает на этот вопрос. А unique_ptr имеет совсем конкретный сценарий: удалить сразу как только выходим за пределы scope, при этом не позволять копирование.
Работа с сырым указателем — да, можно, но... буханка-тролейбус.jpg
А убер-указатели просто так не появляются — там чётко проговаривается сценарий применения.
МР>Т.е. общепринятого подхода в C++ к этому вопросу нет — это зависит от дизайна конкретного проекта.
общепринятости быть не может, вопрос в интерфейсе. бывает функция принимает shared_ptr и, соответсвенно, может сохранить его "у себя", бывает что указателя дотаточно и тем самым функция "говорит", что она будет обращаться к объекту только в теле, бывает ещё unique_ptr в интерфейсе и это значит, что функция ожидает эксклюзивный доступ, есть ещё много разных указателей дающих разную семантику (copy-on-write, create-shared-only, enable-ptr-from-this, и т.д...)
Здравствуйте, Максим Рогожин, Вы писали:
МР>Привет, МР>объясните, пожалуйста, как правильно/лучше делать если функции нужно только читать какие-то свойства объекта, но не нужно его менять:
Если передаваемый объект должен жить столько, сколько требуется DocumentAnalyser передавай shared_ptr и храни shared_ptr. Если передаваемый документ может умереть в процессе обработки, то передавай shared_ptr и храни weak_ptr. Умные указатели не осуществляют контроль доступа к хранимому объекту в многопоточной среде, поэтому здесь уже сам навешивай мьютекты, атомики и т.д. и т.п.
лучше const Document&
передавать const shared_ptr<Document> вообще нет смысла, потому что это функция, и ты увеличиваешь counter на время выполнения функции — а это дорого.
если же нужно в этой функции куда то передать shared_ptr во владение комуто, то дучше const shared_ptr<Document>&