2013-10-02 2 views
27

Является ли стандарт C++ гарантией того, что два указателя на функцию всегда сравниваются одинаково? Я понимаю, что это обычно верно для не-встроенных функций. Но если есть встроенная функция, и указатель на функцию создается в двух отдельных единицах компиляции, будет ли компоновщик сливать два экземпляра, или разрешено ли выпустить дублирующие функции?Являются ли два указателя функций одинаковыми?

Если ответ на вышеизложенное равен «они равны»: сохраняется ли это, если есть общий заголовок с встроенной функцией, и как основная программа, так и динамически загружаемый плагин (общий объект/DLL) создают указатель на функцию?

ответ

26

Раздел §5.10/1 из стандарта C++ 11 говорит:

Два указателя одного и того же типа сравнения равны тогда и только тогда, когда они как нуль, указывают на один и тот же функции, или оба представляют собой один и тот же адреса с

Две копий одного и те же inline функций все та же функция. С точки зрения реализации компилятор будет генерировать копию функции в каждой единицы перевода, но компоновщик затем выбросит одну из копий, чтобы остался только один.

Принимая адрес функции, вы не позволяете ей быть встроенным (отличным от inline, что больше связано с тем, чтобы избежать нарушения правила единой четкости).

DLL не входят в сферу применения стандарта, но только одна копия функции останется в двоичном изображении, поэтому получение адреса функции (например, GetProcAddress) из DLL получит тот же указатель функции, что и код внутри DLL.

+0

Ваш последний вопрос верен только в домене того же процесса. Если DLL «разделяется» другими процессами, функция может иметь разные адреса в разных процессах (а код в DLL будет видеть разные адреса в зависимости от того, какой процесс вызывает его, причем каждый просмотр также представляет собой отдельное «состояние»). Более того, эти «четкие адреса» могут быть «изображениями» одного и того же физического ресурса (которые, таким образом, остаются совместно используемыми), тогда как «состояние» (сегмент данных) будет оставаться другим. –

+6

Я думаю, что ваша формулировка довольно запутанна. Дело в том, что, беря адрес функции, вы никогда не получите «встроенную» копию. Вы получаете описание видимой внешне видимой функции. Это может даже использоваться для принудительного создания шаблона функции, даже если оно не используется иным образом. – sehe

+1

@sehe: Это разумное приближение, но не обязательно истинное. Представьте себе компилятор с «хвостовой вставкой» - если последний оператор функции является «return f()», вставьте весь массив 'f()' и, возможно, поместите небольшой прыжок, чтобы пропустить некоторый код пролога. Теперь у вас есть встроенная функция f, которая также может быть автоматически вызвана. Указатель функции может указывать на эту встроенную копию. Это позволяет стандарт, не уточняя реализацию. Если допускаются такие странности, краткая формулировка часто бывает неточно. – MSalters

8

Является ли стандарт C++ гарантией того, что два указателя на функцию всегда сравнить равные?

Да, два указателя, которые указывают на ту же функцию, сравнивают одинаковые.

ли это по-прежнему имеют место, если есть общий заголовок с инлайн функции, и как основная программа и динамически загружаемая плагин (общий объект/DLL) создать указатель на функцию?

Да, в 7.1.2.p4

встраиваемая функция с внешним связыванием должна иметь один и тот же адрес во всех единицах трансляции.

+0

DLL технически Undefined Beh Avior. Вы не можете просто сказать это просто. На практике нет разумного способа, с помощью которого компилятор будет знать, из какой DLL ему нужно импортировать 'std :: map > :: size()', поэтому вы, вероятно, закончите с несколькими копиями и несколькими адресами. – MSalters

Смежные вопросы