Что делает 'константу, статичную' средний в C и C++?

Как будто вы пытаетесь получить доступ к объекту, который является null. Рассмотрим ниже пример:

TypeA objA;

. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException, что имеет смысл.

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
110
задан Alexis Wilke 14 June 2015 в 21:27
поделиться

10 ответов

Это имеет использование и в C и в C++.

, Поскольку Вы предположили, static, часть ограничивает свой объем тем единица компиляции . Это также предусматривает статическую инициализацию. const просто говорит компилятору не позволять кому-либо изменить его. Эта переменная или помещается в данные или bss сегмент в зависимости от архитектуры, и могла бы быть в памяти, отмеченной только для чтения.

Все, именно так C рассматривает эти переменные (или как C++ рассматривает переменные пространства имен). В C++ участник отметил static, совместно используется всеми экземплярами данного класса. Является ли это частным или не не влияет на то, что одна переменная совместно используется несколькими экземплярами. Наличие const на там предупредит Вас, если какой-либо код попытался бы изменить это.

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

104
ответ дан Community 24 November 2019 в 03:06
поделиться

Много людей дало основной ответ, но никто не указал, что в C++ const значения по умолчанию к static в namespace уровень (и некоторые дали неправильную информацию). Посмотрите C++, который 98 стандартов разделяют 3.5.3.

Сначала некоторый фон:

Единица перевода: исходный файл А после того, как препроцессор (рекурсивно) включал все включать файлы.

Статическая связь: символ А только доступен в своей единице перевода.

Внешняя связь: символ А доступен от других единиц перевода.

В namespace уровень

Это включает глобальное пространство имен иначе глобальные переменные .

static const int sci = 0; // sci is explicitly static
const int ci = 1;         // ci is implicitly static
extern const int eci = 2; // eci is explicitly extern
extern int ei = 3;        // ei is explicitly extern
int i = 4;                // i is implicitly extern
static int si = 5;        // si is explicitly static

На функциональном уровне

static означает, что значение сохраняется между вызовами функции.
семантика функции static переменные подобны глобальным переменным в этом, они находятся в сегмент данных программы (а не стек или "куча"), видят этот вопрос для получения дополнительной информации [приблизительно 117] время жизни переменных.

В class уровень

static означает, что значение совместно используется всеми экземплярами класса и const средства, которые это не изменяет.

199
ответ дан Community 24 November 2019 в 03:06
поделиться

Та строка кода может на самом деле появиться в нескольких различных контекстах и alghough, это ведет себя приблизительно то же, существуют небольшие различия.

Объем Пространства имен

// foo.h
static const int i = 0;

' i' будет видим в каждой единице перевода, которая включает заголовок. Однако, если Вы на самом деле не используете адрес объекта (например'. &i'), я вполне уверен, который компилятор будет рассматривать' i' просто как безопасное с точки зрения типов 0. Где еще два больше единиц перевода берет' &i' тогда, адрес будет отличаться для каждой единицы перевода.

// foo.cc
static const int i = 0;

' i' имеет внутреннюю связь, и так не может быть упомянут от за пределами этой единицы перевода. Однако снова, если Вы не используете его адрес, это будут, скорее всего, рассматривать как безопасное с точки зрения типов 0.

Одна вещь, на которую стоит указать, то, что следующее объявление:

const int i1 = 0;

точно то же как [1 112]. Переменная в пространстве имен, объявленном с [1 113] и не явно объявленная с [1 114], неявно статична. Если Вы думаете об этом, это было намерение комитета по C++ позволить const переменные быть объявленным в заголовочных файлах, всегда не нуждаясь static ключевое слово, чтобы не повреждать ODR.

Объем Класса

class A {
public:
  static const int i = 0;
};

В вышеупомянутом примере, стандарт явно определяет, что' i' не должен быть определен, если его адрес не требуется. Другими словами, если Вы только будете использовать' i' в качестве безопасного с точки зрения типов 0 тогда, то компилятор не определит его. Одно различие между классом и версиями пространства имен - то, что адрес' i' (если используется в двух рудах больше единиц перевода) будет тем же для участника класса. Где адрес используется, у Вас должно быть определение для него:

// a.h
class A {
public:
  static const int i = 0;
};

// a.cc
#include "a.h"
const int A::i;            // Definition so that we can take the address
44
ответ дан Richard Corden 24 November 2019 в 03:06
поделиться

Это - оптимизация небольшого пространства.

, Когда Вы говорите

const int foo = 42;

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

нечто интервала константы экстерна;

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

Теперь, путем объявления, что это статично:

static const int foo = 42;

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

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

namespace {
    const int foo = 42; // same as static definition above
}
22
ответ дан Ferruccio 24 November 2019 в 03:06
поделиться

Это пропускает 'интервал'. Это должно быть:

const static int foo = 42;

В C и C++, это объявляет целочисленную константу с локальным объемом файла значения 42.

, Почему 42? Если Вы уже не знаете (и трудно полагать, что Вы не делаете), это - refernce к Ответ на Жизнь, Вселенную и Все .

8
ответ дан Kevin 24 November 2019 в 03:06
поделиться

В C++,

static const int foo = 42;

предпочтительный способ определить & используйте константы. Т.е. используйте это, а не

#define foo 42

, потому что это не ниспровергает систему безопасности типов.

4
ответ дан paxos1977 24 November 2019 в 03:06
поделиться

Ко всем большим ответам я хочу добавить маленькую деталь:

, Если Вы пишете, плагины (например, DLLs или .so библиотеки, которые будут загружены системой CAD), тогда статичный , жизненное средство сохранения, которое избегает коллизий имени как этот:

  1. системные нагрузки CAD плагин A, который имеет "нечто интервала константы = 42"; в нем.
  2. системные нагрузки плагин B, который имеет "нечто интервала константы = 23"; в нем.
  3. В результате плагин B будет использовать значение 42 для нечто, потому что сменный загрузчик поймет, что уже существует "нечто" с внешней связью.

Еще хуже: Шаг 3 может вести себя по-другому в зависимости от компиляторной оптимизации, сменного механизма загрузки, и т.д.

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

4
ответ дан Black 24 November 2019 в 03:06
поделиться

Да, это скрывает переменную в модуле от других модулей. В C++ я использую его, когда я не хочу/нуждаюсь изменять.h файл, который инициирует ненужное, восстанавливают других файлов. Кроме того, я поместил помехи сначала:

static const int foo = 42;

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

2
ответ дан Jim Buck 24 November 2019 в 03:06
поделиться

Этот ia s глобальная константа, видимая/доступная только в модуле компиляции (.cpp файл). BTW использование статичного с этой целью удерживается от использования. Лучше используйте анонимное пространство имен и перечисление:

namespace
{
  enum
  {
     foo = 42
  };
}
2
ответ дан Roskoto 24 November 2019 в 03:06
поделиться

Создание его частный все еще означало бы, что появляется в заголовке. Я склонен использовать "самый слабый" путь, который работает. См. эту классическую статью Scott Meyers: http://www.ddj.com/cpp/184401197 (это о функциях, но может быть применено здесь также).

1
ответ дан yrp 24 November 2019 в 03:06
поделиться