Есть ли какие-либо преимущества в создании бесплатной статической функции?

#c

#c

Вопрос:

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

Комментарии:

1. Не могли бы вы задать этот вопрос более четко?

2. Какую часть вы не понимаете? Кроме того, почему понижающий голос?

3. Понижающий голос исходит не от меня. А что касается вашего первого вопроса: прочитайте свой оригинальный пост и попытайтесь его понять. И, похоже, вы потеряли несколько персонажей…

4. Есть ли другой b? Да, есть. B.

5. Верно … должно быть, остальная часть вопроса была удалена по ошибке. И теперь я не могу вспомнить, что еще я хотел спросить: D

Ответ №1:

Объявление свободных функций as static дает им внутреннюю связь, что позволяет компилятору проводить более агрессивную оптимизацию, поскольку теперь гарантируется, что никто за пределами TU не сможет увидеть эту функцию. Например, функция может полностью исчезнуть из сборки и быть встроенной везде, поскольку нет необходимости предоставлять версию с возможностью ссылки.

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

Комментарии:

1. Спасибо, тип ответа, на который я надеялся.

2. «вам разрешено иметь разные статические функции с одинаковыми именами в разных TU» — безымянные пространства имен также могут обеспечить этот эффект, если вам нравятся фигурные скобки и дополнительные отступы 😉

3. @SteveJessop: Это правда (и мы не делаем отступы для пространств имен :-)), но было ли это добавлено в C 11? Я имею в виду внутреннюю связь.

4. Да, тот факт, что безымянные пространства имен имеют внутреннюю связь, является новым для C 11.

5. Конечно, компилятор может все это сделать в любом случае? inline Ключевое слово в основном игнорируется в современных компиляторах — «Clang рассматривает его как мягкое предложение от программиста»., Так что это не изменит встраивание, и компоновщик может удалить функции, которые не используются.

Ответ №2:

Поскольку поля комментариев слишком малы, чтобы объяснить, почему у вас серьезная ошибка в ваших рассуждениях, я представляю это как ответ сообщества wiki. Для функций только для заголовков static это практически бесполезно, потому что любой, кто включает свой заголовок, получит другую функцию. Это означает, что вы будете дублировать код, который компилятор создает для каждой из функций (если только компоновщик не может объединить код, но, насколько я знаю, это очень маловероятно), и, что еще хуже, если функция будет иметь локальную статику, каждая из этих локальных будет отличаться, что приведет к потенциально множественным инициализациям длякаждый вызов определения из другого включения. Нехорошо.

Что вам нужно для функций только для заголовков, так это inline (не- static inline ), что означает, что каждое включение заголовка будет определять одну и ту же функцию, а современные компоновщики способны не дублировать код каждого определения, как это сделано для static (во многих случаях стандарт C даже требует, чтобы они это делали), а выдавать толькоодна копия кода из всех определений, созданных всеми включениями.

Комментарии:

1. Я думаю, вы преувеличиваете степень, в которой создание функции inline предотвращает дублирование кода. Пометка inline не мешает компилятору фактически встроить ее, тем самым дублируя значительную часть кода, если не пролог и т. Д. Но это позволяет избежать вероятной ситуации, когда большая static функция может дублироваться даже в ситуациях, когда, учитывая свободу действий, компилятор предпочел бы не вставлять ее.

2. @Steve Я не говорю что-то о встроенных вызовах функций. Ни одно ключевое слово в стандартном C не может предотвратить встроенные вызовы функций, будь то inline функции или static функции. Это дело компилятора, и он будет выполнять встроенные вызовы static и inline функции по своему усмотрению.

3. Вы сказали: «современные компоновщики не будут дублировать код каждого определения». Учитывая существование встраивания, я думаю, что это утверждение вводит в заблуждение. Возможно, более точным было бы: «современные компоновщики способны не дублировать код».

4. @Steve вы правы в отношении вводящего в заблуждение фактора. Однако стандарт даже требует, чтобы компоновщики не дублировали свой код, если вы берете адрес их функции и печатаете его / сравниваете его по TU. И по этой причине, afaik, код, сгенерированный для встроенных функций, помещается в разделы со специальными именами, так что компоновщик может легко выбросить все, кроме одной копии кода. Для static функций ничего подобного не делается. Почему компилятор решил сказать: «Ах, я хочу раздуть код, поэтому я вставил эту встроенную функцию .text , чтобы ее нельзя было объединить!»?

5. @Steve совсем нет 🙂 A static inline имеет разные адреса в разных TU (потому что определения имеют внутреннюю связь и, следовательно, определяют разные функции), нестатический inline имеет одинаковые адреса в разных TU (потому что определения имеют внешнюю связь и, следовательно, определяют одну и ту же функцию). И если у них есть локальная статическая переменная, вы получаете несколько объектов в первом случае и только один объект и инициализацию этого объекта во втором случае.

Ответ №3:

Ответ немного не по порядку, потому что первый рассмотренный пункт вызывает у меня в голове несколько серьезных вопросов.

но поскольку cpp нигде не включен

Я очень надеюсь, что вы никогда #include нигде не найдете исходный файл. Препроцессор не заботится о различии между исходным кодом и заголовком. Это различие существует в основном для того, чтобы приносить пользу людям, а не компиляторам. Есть много причин, по которым вы никогда не должны #include нигде размещать исходный файл.

У меня есть файл .cpp, в котором есть некоторые статические свободные функции. Я знаю, как это поможет в заголовочном файле…

Как это поможет?

Вы объявляете нестатические свободные функции в заголовке, если эти свободные функции имеют внешнюю связь. Объявление (но не определение) статических свободных функций в заголовке не помогает. Это помеха. Вы хотите поместить материал в заголовок, который поможет вам и другим программистам понять экспортируемое содержимое чего-либо. Эти статические свободные функции не являются экспортируемым контентом. Вы можете определить свободные функции в заголовке и, таким образом, сделать их экспортируемым содержимым, но стандартная практика заключается в использовании inline ключевого слова, а не static .

Что касается ваших статических свободных функций в вашем исходном файле, вы можете рассмотреть возможность размещения объявлений этих функций в верхней части исходного файла (но не в заголовке). Это может помочь улучшить понятность. Без этих объявлений организация исходного файла будет выглядеть паскаль, с функциями низкого уровня, определенными в первую очередь. Большинству людей нравится представление сверху вниз. Сначала объявляя функции, вы можете использовать стратегию сверху вниз. Или стратегия наизнанку, или любая другая стратегия упрощает понимание функциональности.

Комментарии:

1. «Большинству людей нравится представление сверху вниз». Я не согласен, но это только мое личное мнение. У вас есть фактическая статистика, подтверждающая это утверждение?