Проблема с конструктором одноэлементного класса является частной в этом контексте

#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; (ссылка) решило проблему.