ключевое слово static в C ++ - PullRequest
       0

ключевое слово static в C ++

5 голосов
/ 21 марта 2012

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

  1. Когда люди говорят, что они недоступны за пределами области видимости, это просто означает, что вы не можете изменить значение (это будет ошибка) за пределами области его идентификации?

  2. Я думал об этом коде:

    #include "iostream"
    
    void staticExample();
    
    int main()
    {
        staticExample();
    
        return 0;
    }
    
    void staticExample()
    {
        for (int i = 1; i <= 10; ++i)
        {
            static int number = 1;
            std::cout << number << "\n";
    
            ++number;
        }
    }
    

и я подумал, что на каждой итерации цикла я устанавливаю переменную 'число' в 1. Как я и ожидал, она печатает 1, 2, 3 .. 10. Имеет ли компиляторпризнать, что строка, устанавливающая его в 1, была объявлением и игнорирует его "изменение"?

Ответы [ 5 ]

3 голосов
/ 21 марта 2012

Дважды вызовите staticExample и посмотрите, что произойдет с вашим выводом. Это поможет вам понять «статическое хранилище» применительно к локальным переменным.

#include <iostream> 

void staticExample()
{
    static int number = 1;

    for (int i = 1; i <= 10; ++i)
    {
        std::cout << number << "\n";
        ++number;
    }
}

int main()
{
    staticExample();  // begins counting at 1
    staticExample();  // begins counting at 10

    return 0;
}

Выход:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

Однажды мне понравилась цитата, которая мне понравилась: «У вас есть стековое хранилище и у вас есть кучное хранилище, но у вас также есть другой тип хранилища. Оно называется статическим и не находится ни в стеке, ни в куче». Не дословно, а что-то похожее на это.

2 голосов
/ 21 марта 2012

Объект оживает один раз и поэтому инициализируется один раз.Инициализация не является назначением.(IINA? い い 、 な!)

1 голос
/ 21 марта 2012

Переменная static (это также верно для static class членов) инициализируется только один раз - глобально .Даже при первом запуске через область, которая объявляет инициализацию, обычно игнорирует инициализацию, хотя может быть какой-то компилятор, который делает это по-другому - так что это зависит от компилятора.

Причина: инициализация обычно происходит за до того, как ваша main() функция будет вызвана и часто даже будет отражаться в самом исполняемом / двоичном файле в том смысле, что статические данные записываются там, предварительно инициализированные во время соединения.Это означает, что данные static большую часть времени будут действительны даже до того, как будет запущен первый фрагмент кода (части среды выполнения C, которые будут вызывать ваш main()).

Кроме указателя /однако для псевдонимов ссылок не было бы способа получить доступ к такой переменной за пределами ее непосредственной области видимости (окружающие скобки {}).

С здесь :

6.7 Оператор объявления

Реализация может выполнять раннюю инициализацию других переменных области блока со статическим или потоковым сроком хранения при тех же условиях, что реализация может статически инициализироватьпеременная со статической или продолжительностью хранения потока в области имен (3.6.2).

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

3.7.1 Статическая продолжительность хранения

Если переменная со статическим sУ длительности torage есть инициализация или деструктор с побочными эффектами, он не должен быть удален, даже если он не используется, за исключением того, что объект класса или его копирование / перемещение могут быть удалены, как указано в 12.8.

... что означает, что имеет смысл static вести себя подобно тому, как это было в C - т.е. инициализировать его содержимое заранее, если инициализация была определена во время компиляции.

Многие компиляторы будутв противном случае инициализация с нуля или с некоторым магическим числом (например, в сборках отладки), когда переменная была объявлена, но не инициализирована во время объявления.

0 голосов
/ 21 марта 2012

Когда люди говорят, что они недоступны за пределами области действия, это просто означает, что вы не можете изменить значение (это приведет к ошибке) за пределами области его определения?

Нет, это не то, что означает сфера. Когда вы используете имя «вне области действия» чего-либо, это означает, что это имя не будет разрешено для сущности, названной внутри рассматриваемой области действия. Имя может преобразовываться в другой объект или может быть недопустимым именем в зависимости от контекста.

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

В вашем примере кода = 1 является инициализатором, а не назначением. Он используется, когда переменная инициализируется, что, поскольку объект объявлен static, происходит только при первом выполнении выполнения через оператор объявления.

0 голосов
/ 21 марта 2012
  1. Это просто означает, что подобный код приведет к сообщению об ошибке компилятора:

    {
        static int x;
        x = 5;
    }
    x = 6;  // Compiler error here!  We're outside the scope that x was declared in.
    

    Но это не значит, что вы не можете получить к нему доступ. Например:

    int *p = NULL;
    {
        static int x;
        x = 5;
        p = &x;
    }
    *p = 6;  // This is fine
    
  2. Статическая переменная инициализируется только один раз; в первый раз это достигнуто.

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