Различие между статическим символом константы* и символом константы*

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

struct Obj1
{
    void Foo()
    {
        const char* str( "hello" );
    }
};

и

struct Obj2
{
    void Foo()
    {
        static const char* str( "hello" );
    }
};
15
задан Will MacDonagh 28 May 2010 в 12:20
поделиться

4 ответа

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

Нестатическая версия будет сохраняться в стеке для каждого вызова функции и уничтожаться после каждого вызова.

Теперь ваш пример немного сложен в отношении того, что на самом деле делает компилятор, поэтому давайте сначала рассмотрим более простой случай:

void foo() {
    static long i = 4;
    --i;
    printf("%l\n", i);
}

А затем основной пример, например, такой:

int main() {
    foo();
    foo();
    return 0;
}

напечатает

3
2

, тогда как с

void foo() {
    long i = 4;
    --i;
    printf("%l\n", i);
}

] он напечатает

3
3

Теперь в вашем примере у вас есть константа, поэтому значение не может быть изменено, поэтому компилятор может сыграть некоторые уловки, хотя это часто не влияет на сгенерированный код, но помогает компилятору обнаруживать ошибки. И тогда у вас есть указатель, и имейте в виду, что статика влияет на сам указатель, а не на значение, на которое он указывает. Таким образом, строка "hello" из вашего примера, скорее всего, будет помещена в сегмент .data вашего двоичного файла, и будет существовать только один раз, пока программа живет, независимо от статики.

18
ответ дан 1 December 2019 в 01:10
поделиться

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

В случае const это не так уж и полезно - по крайней мере, до тех пор, пока построение постоянного значения так же пренебрежимо с точки зрения производительности, как и назначение адреса. (Если объект const не является постоянным выражением или выражение требует значительных ресурсов для создания - как в const Foo bar = foobar (); , где foobar ()) может занять значительное время - разница может стать важной.)

Что действительно имеет значение, так это когда вы хотите вернуть объект по ссылке или указателю: вы не можете вернуть ссылку или указатель на локальный объект, если это не локальный статический объект. ( Спасибо Matthieu за указание на это. ) Однако, когда вы хотите использовать это, вы должны помнить, что локальная статика изначально небезопасна для потоков.

10
ответ дан 1 December 2019 в 01:10
поделиться

Хотя есть техническая разница, с точки зрения использования и эффекта ваши два примера идентичны.

Более подробно, использование ключевого слова static применяется к указателю на строковый литерал, а не к самому строковому литералу. Указатель в примере 1 будет помещен в стек, указатель в примере 2 будет размещен со статическими переменными.

Я был бы удивлен, если бы они оба не были оптимизированы под одно и то же.

2
ответ дан 1 December 2019 в 01:10
поделиться

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

Версия с const char * будет копировать данные из места, доступного только для чтения, в переменную на стеке.

Версия с static const char * ссылается на данные в месте, доступном только для чтения (копирование не выполняется).

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

8
ответ дан 1 December 2019 в 01:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: