глобальный std::string и одно правило определения

У меня есть заголовочный файл, содержащий следующее определение

const std::string error[] = {"a", "b"};

Теперь я включаю этот файл в две разные единицы перевода и компилирую исходные коды. Все работает, но почему? Ожидается, что это сломает one definition rule.

Теперь еще интереснее, меняю тип

const char* error[] = {"a", "b"};

и вот она, ожидаемая ошибка

multiple definition of `error'

Это работает так же, как и для std::string для int, char, short и других целочисленных типов. Что это?


person axe    schedule 25.11.2013    source источник


Ответы (3)


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

static const std::string error[] = {"a", "b"};

Второй не работает, потому что это не переменная, которая является константой, а chars, из которых она состоит.

person Luchian Grigore    schedule 25.11.2013
comment
Не знал, что const дает внутреннюю связь. Спасибо. Это указано в стандарте? - person axe; 25.11.2013
comment
Да, нашел. Objects declared const and not explicitly declared extern have internal linkage. - person axe; 25.11.2013
comment
@axe Что за отсылка? - person BoBTFish; 25.11.2013
comment
Не бери в голову. Это 7.1.1 Спецификаторы класса хранилища [dcl.stc], параграф 7. - person BoBTFish; 25.11.2013
comment
Также обратите внимание, что это одно из немногих мест, где C++ нарушает совместимость с C. См. этот вопрос для получения подробной информации и обоснования. - person ComicSansMS; 25.11.2013

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

Второй пример не const — указатели указывают на константные объекты, но сами являются изменяемыми. Таким образом, этот массив имеет внешнюю связь и подчиняется правилу единого определения.

person Mike Seymour    schedule 25.11.2013

Из MSDN

В C постоянные значения по умолчанию имеют внешнюю связь, поэтому они могут появляться только в исходных файлах. В C++ постоянные значения по умолчанию имеют внутреннюю связь, что позволяет им появляться в файлах заголовков.

person Sergei Nikulov    schedule 25.11.2013