Какой класс хранения является статическим внутри функции и почему?

Если я использую одноэлементный шаблон (да, я знаю - они обычно плохие)... и у меня была такая функция экземпляра:

MySingleton* Instance() {
    static MySingleton instance;
    return &instance;
}

какой класс хранения instance?

Я читаю "Программирование с потоками POSIX" Дэвида Р. Бутенхофа и наткнулся на текст, в котором говорилось:

В большинстве случаев вы, вероятно, будете объявлять условные переменные, используя внешний или статический класс хранения в области файла, то есть вне какой-либо функции. У них должен быть обычный (внешний) класс хранения, если они используются другими файлами, или статический класс хранения, если они используются только внутри файла, в котором объявлена ​​переменная.

Поскольку этот статический объект находится внутри функции, он автоматический? или класс отличается из-за статического ключевого слова?

Если бы я переместил переменную «экземпляр» в статическую и глобальную (не в какую-либо функцию) в своем файле, мог бы я по-прежнему ссылаться на нее в другом файле или это не сработало бы?


person John Humphreys    schedule 10.01.2012    source источник


Ответы (3)


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

Ваша переменная области действия функции instance имеет статическую продолжительность хранения. Без ключевого слова static у него была бы автоматическая продолжительность хранения.

Объект в области файла всегда имеет статическую продолжительность хранения (ну, или продолжительность хранения потока в C++11 с ключевым словом thread_local). Использование ключевого слова static в области файла дает объекту внутреннюю связь, extern дает ему внешнюю связь, они не влияют на продолжительность хранения.

Описание того, что что-то имеет «статический класс хранения», является правильным, поскольку static является так называемым «спецификатором класса хранения», но это не вся история, поскольку значение static в области файла отличается от значения в области действия функции.

Вы можете передать ссылку на объект со статической продолжительностью хранения коду из других единиц перевода. Неважно, имеет ли он область действия файла или области действия функции, и не имеет значения, какова его связь. «У них должен быть нормальный (внешний) класс хранения, если они используются другими файлами» просто означает, что глобальный объект нуждается во внешней связи, если другие файлы будут ссылаться на него по имени, поскольку глобальное имя с внутренняя связь относится к разным объектам в каждой TU. Технически это имя имеет связь, а не объект.

person Steve Jessop    schedule 10.01.2012
comment
Спасибо за ответ - вы попали в точку с тем, что меня смутило :) Вы знаете хороший ресурс для изучения этого материала? Я не сталкивался с этим (каким-либо значительным образом) ни в одной из моих книг по C++ - просто странные ссылки, которые недостаточно существенны, чтобы учиться. - person John Humphreys; 10.01.2012
comment
@w00te: стандарт. Прочитайте полные разделы о продолжительности хранения, компоновке и спецификаторах класса хранения. Затем перечитайте раздел о компоновке, потому что, хотя компоновка сама по себе довольно проста, правила для нескольких объявлений с разными спецификаторами класса хранения сбивают меня с толку. Затем, наконец, вероятно, стоит прочитать что-нибудь конкретное о реализации о том, как импорт/экспорт DLL обрабатывается вашим компилятором, поскольку, хотя это и не то же самое, что компоновка, она очень тесно связана. - person Steve Jessop; 10.01.2012
comment
Спасибо, я добавлю это в свой список для чтения - хотя звучит так, будто это может поставить меня в положение эмбриона :) - person John Humphreys; 10.01.2012

instance имеет класс хранения Static, так как он соответствует квалификатору static, без которого он был бы automatic переменной с локальной областью действия.
статические переменные, объявленные в области файла, имеют внутреннюю связь, и вы не можете использовать их в разных файлах.
если вы хотите объявить глобальную переменную, которую можно использовать в файлах, тогда вам нужно использовать extern, которая дает внешнюю связь переменной.

person Alok Save    schedule 10.01.2012
comment
Итак, экземпляр (в примере с синглтоном) можно использовать в файлах, но если бы я объявил его в области файла, я не смог бы использовать его в файлах? - person John Humphreys; 10.01.2012
comment
@ w00te: Нет. Статическая внутренняя функция имеет область действия, ограниченную только этой функцией, в то время как статическая функция в файле имеет область действия, ограниченную только этим файлом. - person Alok Save; 10.01.2012
comment
Итак, этот одноэлементный метод не работает или все в порядке, потому что указатель возвращается в ячейку памяти, и мы уверены, что эта ячейка сохраняется, потому что она статическая? - person John Humphreys; 10.01.2012
comment
На самом деле я понял - спасибо :) +1 за полезное решение. - person John Humphreys; 10.01.2012
comment
@ w00te: поскольку переменная является статической, она гарантированно будет существовать на протяжении всей жизни программы, и, поскольку вы возвращаете ее явно как возвращаемое значение, ее можно использовать в разных файлах (единицах перевода). - person Alok Save; 10.01.2012

Как правило, в проектах используется шаблон Singleton, поэтому в этом проекте будет использоваться только один экземпляр. например, генераторы пула соединений с БД или конфигурация. Синглтон используется следующим образом: экземпляр, который всегда будет вызываться, должен быть статическим и приватным в классе, конструктор класса должен быть приватным, функция getInstance должна быть общедоступной. Давайте посмотрим ниже:

/**
 * @author harzumanian
 *
 */
public class LogManager {

    private File file = null;
    private static LogManager logger = null;

    /**
     * 
     */
    private LogManager() {
        file = new File(Constants.PLUGIN_LOG);
    }

    public static LogManager getLogger() {
        if (logger == null) {
            logger = new LogManager();
        }
        return logger;
    }
}
person GingerHead    schedule 10.01.2012