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

Я слышал, как утверждается, что использование безымянных пространств имен в 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, я почти уверен, что требование внешней связи для безымянного пространства имен было удалено, и теперь оно ведет себя точно так же, как статический уровень пространства имен. Кто-то более знакомый со стандартом может подтвердить / опровергнуть это.

Другие вопросы по тегам