Эта строка кода может фактически появляться в нескольких различных контекстах, и хотя она ведет себя примерно одинаково, есть небольшие различия.
Область пространства имен
// 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;
равно точно так же, как static const int i = 0
. Переменная в пространстве имен, объявленная с const
и не объявленная явно с extern
, является неявно статической. Если вы подумаете об этом, то комитет 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