Интеллектуальный компоновщик может распознать, когда два разных тела функций идентичны, и объединить их вместе в один символ. Это называется «свертывание COMDAT» в MSVC и «удаление дубликатов» в большинстве других мест. Например, следующие две функции могут компилироваться в PPC одинаково, хотя и принимают разные типы, потому что типы имеют одинаковый размер и ведут себя одинаково в данной ситуации.
template<typename T>
GetLowBit( T foo ) { return T & 1; }
GetLowBit<unsigned long>(ulong x); // compiles to "li r4, 1 ; and r3, r3, r4 ; blr "
GetLowBit<signed long>(long x); // also compiles to "li r4, 1 ; and r3, r3, r4 ; blr "
и поэтому компоновщик может сделать так, чтобы оба их «имени» указывали на одно и то же место, так что вызов GetLowBit<unsigned long>
идет по тому же адресу, что и вызов GetLowBit<signed long>
. Таким образом, в общем случае можно складывать вместе различные экземпляры шаблонов функций, которые работают с одинаковыми размерами шрифта одинаковым образом. (В частности, контейнеры, в которых хранятся указатели или перечисления, обычно складываются вместе.)
Это происходит не только с шаблонными функциями. Некоторые компоновщики могут заметить, когда любые две функции имеют одинаковые тела, и объединить их. В частности, я вижу, что MSVC имеет тенденцию сворачивать каждую виртуальную функцию, которая ничего не делает, кроме возврата, в одну убер-функцию, например, для
class A
{
virtual void nothing() {};
}
class B
{
virtual void empty() {};
}
Я часто вижу (в дизассемблере при отладке чего-то еще), что записи vtable для nothing
и empty
указывают на одно и то же тело функции, которое, в свою очередь, является просто ret
.
Вы можете рассчитывать на это? Нет. Это функция, которую интеллектуальный компоновщик может предоставить функциям, когда заметит их. Ваш компоновщик может быть глупым, там много паршивых компиляторов. Это может произойти только в том случае, если вы предоставите определенные аргументы команды. Это может произойти для некоторых функций, но не для других по причинам, известным только компоновщику. Он может даже отличаться от сборки к сборке в зависимости от того, что еще есть в программе.
Так что в целом да, это может произойти, и когда это происходит, это может быть хорошей экономией на размере исполняемого файла. Но вы не можете рассчитывать на это, если вы не очень хорошо знакомы со своим компоновщиком и всеми его функциями.
person
Crashworks
schedule
20.11.2010