Следует ли избегать безымянных функций пространства имен, чтобы уменьшить размеры таблицы символов?
Я слышал, как утверждается, что использование безымянных пространств имен в C++ для определения функций и гарантии того, что они не могут быть вызваны извне модуля компиляции, в котором они определены, не очень хорошо в очень больших средах кода, потому что они вызывают рост таблицы символов неоправданно большой, включив записи в эти символы в автоматически сгенерированные пространства имен, которые компилятор C++ предоставляет, когда они не названы.
namespace {
// This function can only be accessed from hear to the end of
// any compilation unit that includes it.
void functionPerhapsInsertedIntoSymbolTable() {
return;
}
}
Возможно, это с учетом того, что вышеприведенное должно быть таким же, как выполнение следующих действий:
namespace randomlyGenerateNameHereNotCollidingWithAnyExistingNames {
// This function can only be accessed from hear to the end of
// any compilation unit that includes it.
void functionPerhapsInsertedIntoSymbolTable() {
return;
}
}
using randomlyGenerateNameHereNotCollidingWithAnyExistingNames;
Однако действительно ли это так просто, требуется ли компилятору сделать запись в таблице символов для символов в сгенерированном имени пространства имен?
Вместо этого в таких ситуациях я слышал, что предлагается использовать статическое объявление:
// This function can only be accessed from hear to the end of
// any compilation unit that includes it.
static void functionNotInsertedIntoSymbolTable() {
return;
}
Правда ли, что использование статического объявления перед функцией вместо помещения его в безымянное пространство имен приводит к тому, что функция становится недоступной вне модуля компиляции, в котором она определена? Есть ли какая-то разница между этими двумя подходами, кроме того, что они потенциально не приводят к росту таблицы символов?
Является ли проблема с раздутием таблицы символов из-за безымянных пространств имен просто ошибкой в некоторых реализациях C++ или стандарт требует компилятора для создания записей для таких функций? Если это раздувание считается ошибкой, существуют ли известные компиляторы, для которых это не проблема?
2 ответа
Правда ли, что использование статического объявления перед функцией вместо помещения его в безымянное пространство имен приводит к тому, что функция становится недоступной вне модуля компиляции, в котором она определена?
Да.
Namespace-static
был объявлен устаревшим в C++03 в пользу неназванных пространств имен, но на самом деле не рекомендуется в C++11, когда все поняли, что это одно и то же, и что не было никакого смысла в устаревании.
Есть ли разница между этими двумя подходами
Нет, не совсем. Могут быть некоторые мелкие тонкости с поиском имен из-за использования пространства имен, но я не могу думать ни о каком прямо сейчас.
кроме того, что потенциально не вызывает рост таблицы символов?
Так как это language-lawyer
Вопрос без очевидной практической проблемы, которую я должен решить, я должен указать, что язык C++ не имеет понятия таблицы символов и, следовательно, не указывает на этот эффект.
Это также не будет иметь никакого заметного эффекта, пока у вас не появятся десятки тысяч безымянных пространств имен; вы?
Причиной для безымянного пространства имен и устаревания статического уровня пространства имен является неудачное ключевое слово export.
Все, на что опирается экспортируемый шаблон, должно быть доступно по ссылкам в точках реализации, которые, скорее всего, находятся в разных исходных файлах. Безымянное пространство имен допускает статический аспект приватизации, сохраняя при этом связь для экспортируемых шаблонов.
Теперь, когда экспорт был удален в C++2011, я почти уверен, что требование внешней связи для безымянного пространства имен было удалено, и теперь оно ведет себя точно так же, как статический уровень пространства имен. Кто-то более знакомый со стандартом может подтвердить / опровергнуть это.