#c #singleton
#c #одноэлементный
Вопрос:
Я пытаюсь написать одноэлементный класс, и я следовал стандартному шаблону, как показано ниже. Но я получаю /usr/include/c /7/ext/new_allocator.h:136:4: ошибка: является закрытой в этом контексте { ::new((void *)__p) _Up(std::forward<_Args>(__args)…);}
status_publisher.hpp
namespace test {
class StatusPublisher {
public:
static std::shared_ptr<StatusPublisher> getStatusPublisher();
private:
StatusPublisher();
static std::shared_ptr<StatusPublisher> instance_;
}
status_publisher.cpp
namespace test {
std::shared_ptr<StatusPublisher> StatusPublisher::getStatusPublisher() {
if(instance_.get()==nullptr) {
instance_ = std::make_shared<StatusPublisher>();
}
return instance_;
}
StatusPublisher::StatusPublisher() {
// Some code
}
}
Ответ №1:
Поскольку instance_ изначально не является shared_ptr в вашем коде, функция .get() не будет там работать, поскольку instance_ не является объектом like shared_ptr<StatusPublisher> { nullptr }
. Я предлагаю вам переместить объявление instance_ в StatusPublisher::getStatusPublisher и вернуть экземпляр туда. Поскольку он объявлен статическим, будет создан только один экземпляр.
Редактировать: я видел другой альтернативный ответ, который предлагает использовать необработанный указатель. Однако, поскольку shared_ptr имеет некоторые преимущества для использования необработанного указателя, я все равно предлагаю версию shared_ptr:
status_publisher.hpp
namespace test {
class StatusPublisher {
public:
static std::shared_ptr<StatusPublisher> getStatusPublisher();
private:
StatusPublisher();
};
}
status_publisher.cpp
namespace test {
std::shared_ptr<StatusPublisher> StatusPublisher::getStatusPublisher() {
static std::shared_ptr<StatusPublisher> instance_ = std::shared_ptr<StatusPublisher>{new StatusPublisher()};
return instance_;
}
StatusPublisher::StatusPublisher() {
// Some code
}
}
Комментарии:
1. Было бы неплохо объяснить OP, почему они получают ошибку, а также перечислить те плюсы
shared_ptr
использования, которые вы советуете. Я их не вижу, потому что, создаваяinstance_
статическую область::getStatusPublisher()
видимости, она в основном гарантированно инициализируется только один раз, а затем нет смысла использоватьshared_ptr
, и OP может использовать одноэлементную реализацию учебника.2. @blami Поскольку shared_ptr поддерживает RAII, он обеспечивает более безопасный доступ (с меньшей вероятностью утечки) к памяти. Это преимущество shared_ptr и unique_ptr . Необработанный указатель может давать меньшие накладные расходы, чем интеллектуальные указатели, программист должен тщательно управлять им вручную, что имеет больше потенциальных шансов внести какую-либо ошибку в программу
3. Я согласен с @blami,
shared_ptr
в этом случае нет никакого преимущества в использовании. Тот факт, что он статичен, означает, что он не будет уничтожен до тех пор, пока программа все равно не завершит работу.4. @MarkRansom Может быть, мы можем просто использовать статический экземпляр statuspublisher_ и изменить возвращаемый тип StatusPublisher::getStatusPublisher() на StatusPublisheramp; . ДА. Это кажется допустимым и более элегантным решением.
5. Спасибо, ребята.. На самом деле переключение на статический StatusPublisheramp; (ссылка) решило проблему.