Должен ли я использовать статический или встроенный?

Я пишу библиотеку только для заголовков, и я не могу определиться с объявлением функций, которые я предоставляю пользователю static или же inline, Есть ли какая-то причина, почему я должен предпочесть одно другому в этом случае?

1

Решение

Они оба предоставляют разные функциональные возможности.

Есть два последствия использования inline ключевое слово (§ 7.1.3 / 4):

  1. Это Рекомендации компилятор, который заменяет тело функции в точке вызова, предпочтительнее обычного механизма вызова функции.
  2. Даже если внутренняя замена не указана, другие правила (особенно w.r.t Одно Правило Определения) для inline следуют.

static Ключевое слово на функцию заставляет inline функция иметь внутреннюю связь (встроенные функции имеют внешнюю связьКаждый экземпляр такой функции рассматривается как отдельная функция (адрес каждой функции отличается) и каждый экземпляр этих функций имеет свои собственные копии статических локальных переменных & строковые литералы (встроенная функция имеет только одну копию этих)

6

Другие решения

static а также inline ортогональны. Другими словами, вы можете иметь один или оба или ни одного. Каждый из них имеет свое отдельное использование, которое определяет, использовать их или нет.

3

Примечание: этот ответ для C ++. Для C см. ответ кафе. Два языка отличаются.

static имеет два соответствующих значения:

  • Для функции в области имен static дает функцию внутренняя связь, что на практике означает, что имя не видно компоновщику. static может также использоваться для данных, но для данных это использование устарело в C ++ 03 (§D.2 в C ++ 03, Приложение D, нормативное). Тем не менее, константы имеют внутреннюю связь по умолчанию (не рекомендуется делать это явным, поскольку использование данных не рекомендуется).

  • Для функции в классе, static удаляет неявное this аргумент, так что функция Можно быть вызванным без объекта класса.

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

Общепринятое соглашение состоит в том, чтобы вместо этого использовать вложенное пространство имен detail, когда нужны классы или функции, которые не являются частью интерфейса открытого модуля, и они хотят уменьшить загрязнение обычного пространства имен (то есть уменьшить вероятность конфликта имен). Это соглашение используется библиотекой Boost. Так же, как и с включенными защитными символами, это соглашение означает отсутствие поддержки модулей в текущем C ++, где один сводится к моделированию некоторых важных языковых функций с помощью соглашений.

Слово inline также имеет два соответствующих значения:

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

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

Первое значение является единственным гарантированным значением inline,

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

Итак, хотя кажется, что вы немного запутались в значениях static а также inline — они не взаимозаменяемы! — вы по сути правы, что static а также inline как-то связаны. Перемещая (свободную) функцию из класса в область имен, вы бы изменили staticinlineи перемещая функцию из области пространства имен в класс, вы бы изменили inlinestatic, Хотя это не обычное дело, я обнаружил, что это не редкость при рефакторинге кода только для заголовков.

Подводя итог:

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

  • Используйте некоторое специальное вложенное пространство имен, например, называется detail чтобы избежать загрязнения внутренними названиями деталей реализации.

  • использование static для статических учеников.

  • Не использовать static сделать явным, что константа имеет внутреннюю связь, потому что это использование static устарела в C ++ 03 (хотя очевидно, что в C ++ 11 устаревшая версия была удалена).

  • Имейте в виду, что пока inline не может быть применен к данным, можно достичь примерно того же (практического) эффекта с помощью шаблонов. Но там, где вам нужен большой кусок общих постоянных данных, реализованных в заголовке, я рекомендую создать ссылку на данные через inline функция. Гораздо проще кодировать и гораздо проще понять читателю кода. 🙂

3

Если эта функция не разделяет состояние класса: static, Сделать функцию static может принести пользу от вызова в любом месте.

Если функция относительно мала и понятна: inline

1

(Этот ответ основан на правилах C99; ваш вопрос помечен как C, так и C ++, и правила в C ++ могут отличаться)

Если вы объявите функцию просто inlineто определение вашей функции встроенное определение. Компилятору не требуется использовать встроенное определение для всех вызовов функции в модуле перевода — можно допустить, что существует внешнее определение той же функции, предоставленной в другом модуле перевода, и использовать это для некоторых или всех вызовов , В случае библиотеки только с заголовком, там будет не быть таким внешним определением, поэтому программы, использующие его, могут потерпеть неудачу во время соединения с отсутствующим определением.

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

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector