Я пытаюсь изучить и понять искажение имени в C++. Вот некоторые вопросы:
(1) От devx
Когда глобальная функция перегружается, сгенерированное скорректированное имя для каждой перегруженной версии уникально. Искажение имени также применяется к переменным. Таким образом локальная переменная и глобальная переменная с тем же пользовательским именем все еще получают отличные скорректированные имена.
Есть ли другие примеры, которые используют искажение имени помимо перегрузки функций и того-же-имени глобальные и локальные переменные?
(2) От Wiki
Потребность возникает, где язык позволяет различным объектам быть названными с тем же идентификатором, пока они занимают другое пространство имен (где пространство имен обычно определяется модулем, классом или явной директивой пространства имен).
Я не вполне понимаю, почему искажение имени только применяется к случаям, когда идентификаторы принадлежат различным пространствам имен, начиная с перегрузки функций может быть в том же пространстве имен и том-же-имени, которым глобальные и локальные переменные могут также быть в том же пространстве. Как понять это?
Переменные с тем же именем, но в различных объемах также используют искажение имени?
(3) C имеет искажение имени? Если это не делает, как это может иметь дело со случаем, когда некоторые глобальные и локальные переменные имеют то же имя? C не имеет перегружающихся функций, правильно?
Спасибо и всего наилучшего!
C не изменяет имена, но добавляет подчеркивание к именам функций, поэтому printf (3)
на самом деле является _printf
в объекте libc.
В C ++ дело обстоит иначе. История этого состоит в том, что изначально Страуструп создал "C с классами" или cfront , компилятор, который переводил ранний C ++ на C. Затем остальные инструменты - компилятор C и компоновщик, которые мы использовали бы для создания объектного кода. . Это означало, что имена C ++ нужно было каким-то образом переводить в имена C. Это именно то, что делает изменение имени . Он предоставляет уникальное имя для каждого члена класса, а также функции и переменной глобального / пространства имен, поэтому имена пространств имен и классов (для разрешения) и типы аргументов (для перегрузки) каким-то образом включены в окончательные имена компоновщика.
Это очень легко увидеть с помощью таких инструментов, как nm (1)
- скомпилируйте исходный код C ++ и посмотрите на сгенерированные символы. Следующее находится в OSX с GCC:
namespace zoom
{
void boom( const std::string& s )
{
throw std::runtime_error( s );
}
}
~$ nm a.out | grep boom
0000000100001873 T __ZN4zoom4boomERKSs
И в C, и в C ++ локальные (автоматические) переменные не производят символов, но находятся в регистрах или в стеке.
Локальные переменные не имеют имен в результирующем объектном файле по той простой причине, что компоновщику не нужно о них знать. Так что без имени, без искажений. Все остальное (на что компоновщик должен обратить внимание) в C ++ искажено по именам.
Существуют ли другие примеры, использующие изменение имен, помимо функций перегрузки и одноименных глобальных и локальных переменных?
C ++ всегда искажает все символы. Компилятору просто проще. Обычно искажение кодирует что-то, связанное со списком или типами параметров, поскольку это наиболее частые причины необходимости искажения.
C не искажает. Область видимости используется для управления доступом к локальным и глобальным переменным с одинаковым именем.
Mangling - это просто то, как компилятор делает счастливым компоновщика.
В C нельзя иметь две функции с одинаковыми именами, независимо от того, что именно. Поэтому компоновщик был написан так, чтобы предполагать уникальные имена. (Вы можете иметь статические функции в разных единицах компиляции, потому что их имена не интересуют компоновщика.)
В C++ вы можете иметь две функции с одинаковыми именами, если у них разные типы параметров. Поэтому C++ объединяет имя функции с типами каким-то образом. Таким образом компоновщик воспринимает их как разные имена.
Обратите внимание, что не имеет значения, как именно имя будет искажено, и на самом деле каждый компилятор делает это по-своему. Важно лишь то, что каждая функция с одинаковым базовым именем каким-то образом становится уникальной для компоновщика.
Теперь вы видите, что добавление пространств имен и шаблонов продолжает расширять этот принцип.
Технически это «украшение». Это звучит менее грубо, но в то же время подразумевает, что CreditInterest
может быть преобразован в IntCrederestit
, тогда как то, что происходит на самом деле, больше похоже на _CreditInterest @ 4
, что справедливо для говорят, "украшены" больше, чем покалечены. Тем не менее, я тоже называю это искажением :-), но вы найдете больше технической информации и примеров, если будете искать «украшение имени C ++».