Есть ли проблема с этой единственной реализацией? - PullRequest
9 голосов
/ 10 февраля 2012

Я обычно привык к реализации одноэлементного шаблона таким образом, потому что это так просто:

class MyClass
{
    public:
        MyClass* GetInstance()
        {
            static MyClass instance;
            return &instance;
        }

    private:
        //Disallow copy construction, copy assignment, and external
        //default construction.
};

Это кажется значительно проще, чем создание статического указателя экземпляра, инициализация его в исходном файле ииспользование динамического выделения памяти в функции экземпляра с защитой.

Есть ли обратная сторона, которую я не вижу?Это выглядит поточно-ориентированным для меня, потому что я думаю, что первый поток, который попадет на первую строку, вызовет создание экземпляра - и это выглядит красиво и лаконично.Я полагаю, что должна быть проблема, которую я не вижу, потому что это не часто встречается - я хотел бы получить некоторую обратную связь, прежде чем я продолжу ее использовать

Ответы [ 5 ]

3 голосов
/ 10 февраля 2012

Недостатком является то, что вы не можете контролировать, когда именно объект уничтожен. Это будет проблемой, если другие статические объекты попытаются получить к нему доступ от своих деструкторов.

Компилятор, совместимый с C ++ 11, должен реализовывать это потокобезопасным способом; однако старые компиляторы могут этого не делать. Если вы сомневаетесь, и вам особенно не нужна ленивая инициализация, вы можете принудительно создать объект, вызвав метод доступа перед запуском любых потоков.

3 голосов
/ 10 февраля 2012

Это не присущее поточно-безопасному решению: при создании экземпляра другой поток может выгрузить экземпляр и попытаться получить его, что приведет либо к двойному экземпляру, либо к использованию неструктурированного экземпляра.несколько компиляторов путем добавления защиты (в gcc, я думаю, есть флаг для отключения этого), потому что нет способа защитить это с помощью пользовательского мьютекса.

2 голосов
/ 10 февраля 2012

В интерфейсе есть две проблемы:

  • Вы должны вернуть ссылку
  • Вы должны сделать либо деструктор, либо оператор delete private

Кроме того, существует небольшой риск попытки использования этого класса после его уничтожения.

Относительно ваших проблем с многопоточностью (и инициализации, я думаю): все хорошо в C ++ 11 и в течение долгого времени хорошо работало на хороших компиляторах C ++.

0 голосов
/ 10 февраля 2012

Вообще говоря, квалификатор static для локальной переменной в методе не гарантирует, что переменная создается только один раз.Если метод вызывается разными потоками, его можно создать один раз для каждого потока столько раз, сколько его вызвали многие потоки.Его не следует путать со статическим членом класса, который создается один раз до запуска программы.Потоковая безопасность локальных статических переменных зависит от конкретной реализации c ++.Полезная ссылка: Являются ли статические переменные функции поточно-ориентированными в GCC?

Надеюсь, это поможет.

0 голосов
/ 10 февраля 2012

Помимо многопоточного сценария - нет.Хорошо - позвольте мне это квалифицировать, строительство лениво (поэтому первый вызов может иметь удар) и разрушение - ну, нет никакой гарантии (кроме этого будет - в некоторый момент)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...