Вопрос по static, c++, inline – Никогда не следует использовать статическую встроенную функцию?

54

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

It hints the compiler that substitution of function body at the point of call is preferable over the usual function call mechanism. Even if the inline substitution is omitted, the other rules(especially w.r.t One Definition Rule) for inline are followed.

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

Далее w.r.t#2Как я понимаю, когда вы объявляете функцию какstatic inline функция,

static Ключевое слово на функцию заставляетinline функция иметь внутреннюю связь (inline functions have external linkageКаждый экземпляр такой функции рассматривается как отдельная функция (address of each function is different) и каждый экземпляр этих функций имеет свои собственные копии статических локальных переменных & amp; строковые литералы (an inline function has only one copy of these)

Таким образом, такая функция действует как любая другаяstatic функция и ключевое словоinline больше не имеет значения, оно становится излишним.

Итак, практически маркировка функцииstatic а такжеinline оба не имеют никакого смысла. Либо это должно бытьstatic(not most preferred) или жеinline(most preferred),
Итак, используетstatic а такжеinline вместе на функцииpractically бесполезный?

@ Наваз: Нет, это не то, что говорит стандарт (I nowhere claimed it does), Я говорю это, и это основано на поведении большинства основных компиляторов. Обычно стандарт ничего не говорит оimplementations это говорит только оobservable behaviors Этот вопрос о практичности. Alok Save
Это то, что говорится в стандарте & gt; & gt;Usually any mainstream compiler will substitute function body at the point of call if needed, so marking function inline merely for #1 is not really needed. Nawaz
Откуда фрагмент & quot; и каждый экземпляр этих функций имеет свои собственные копии статических локальных переменных & amp; строковые литералы & quot; родом из? Jonas Byström
Мысль, которую я добавил бы для ясности, что этот вопрос оstatic inline функции, которые не являются методами класса. Заstatic inline methods, смотретьhere. Sam Kauffman
@ JonasBystr & # XF6; м:§ 7.1.3/4 "If a function with *external linkage объявляется inline в одной единице перевода, она объявляется inline во всех единицах перевода, в которых она появляется; Диагностика не требуется. Встроенная функцияwith external linkage должен иметь одинаковый адрес во всех единицах перевода. Статическая локальная переменная вextern inline Функция всегда ссылается на один и тот же объект. Строковый литерал в телеan extern inline функция - это один и тот же объект в разных единицах перевода * & quot ;. Функция помеченаstatic не имеет внешней связи, поэтому применяется обратное. Alok Save

Ваш Ответ

5   ответов
44

но не обязательно подразумевает бесполезность. Даже если большинство компиляторов выполняют автоматически встроенные функции (причина № 1), лучше всего объявитьinline просто чтобы описать намерение.

Не обращая внимания на взаимодействие сinline, static функции следует использовать с осторожностью.static модификатор в области именного пространства ранее считался устаревшим в пользу безымянных пространств имен (C ++ 03 & # xA7; D.2). По какой-то неясной причине, которую я не могу вспомнить, она была удалена из устаревшей в C ++ 11, но она вам редко нужна.

So, Practically marking a function static and inline both has no use at all. Either it should be static(not most preferred) or inline(most preferred),

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

Какиеis предпочтительным является использование безымянного пространства имен вместоstatic:

namespace {
    inline void better(); // give the function a unique name
}

static inline void worse(); // kludge the linker to allowing duplicates
@Als:static а такжеnamespace{} сделать (примерно) то же самое.inline делает что-то еще Не недооценивайте ценность описания намерения. Если вы должны иметь эффекты,inline объявление может сделать компилятор более агрессивным в отношении встраивания. Из того, что вы уже сказали, может показаться, что вы, возможно, неправильно использовали эти спецификаторы для функций с объявлениями в.h и определения в.cpp, что не так.
@ Алс: независимо от того, где он появляется, более полезноmaintainers кода, чтобы объявить предполагаемое или предполагаемое поведение кода. Это не очень полезно дляusers кода - независимо от того, имеет ли функция значение inline или нет (в идеале) для них.
Но обычно можно добавитьinline в * определении * (файл cpp) & amp; не * объявление * (заголовок) функции, так как это помогает описательным пользователям моего кода? Это может быть полезно для тех, кто может видеть только исходные файлы. Alok Save
@ JohannesSchaub-litb Ну, они не обязательно совпадают. Они достигают того же, что и в видимости между TU в C ++, но эффекты ABI / двоичного формата могут отличаться.static не гарантируется создание видимого уникального имени, такого какnamespace{} является. В чем была причина недооценки? Была ли это ассоциация имен ADL, необходимость иметь функцию для языковой связи или что-то еще? Если ADL, это не исправленоinline Пространства имен?
нет понятия предпочтения безымянного пространства имен статическому. оба имеют одинаковый эффект в отношении связи.
20

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

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

Пример:

source1.cpp:

inline int Foo()
{
  return 1;
}

int Bar1()
{
  return Foo();
}

source2.cpp:

inline int Foo()
{
  return 2;
}

int Bar2()
{
  return Foo();
}

Без использования static on Foo (или без использования анонимного пространства имен, что является предпочтительным способом для большинства программистов на C ++), этот пример нарушает ODR и результаты не определены. Вы можете протестировать в Visual Studio результат Bar1 / Bar2 будет зависеть от настроек компилятора - в конфигурации отладки и Bar1, и Bar2 будут возвращать одно и то же значение (встраивание не используется, одна реализация выбрана произвольно компоновщиком), в конфигурации Release каждый из них вернет предполагаемое значение.

& Quot; Использованиеstatic inline имеет смысл, когда встроенная функция не используется за пределами модуля перевода. & quot;static имеет смысл, добавляяinline это бессмысленно.
1

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

Вы не против предоставить источник для этого?
9

free функции (namespace сфера), то ваше предположение верно.static inline функции действительно не имеют большого значения. Такstatic inline это простоstatic функция, которая автоматически удовлетворяет ODR иinline является избыточным для целей ODR.

Однако когда мы говорим оmember методы (class сфера),static inline Функция имеет значение.
Как только вы объявитеclass метод какinlineего полное тело должно быть видимым для всех единиц перевода, включаяclass.

Помни чтоstatic Ключевое слово имеет другое значение, когда речь идет оclass.
Edit: Как вы можете знать, чтоstatic функция внутриclass другими словами, не имеет внутренней связиa class cannot have different copies of its static method depending on the translation (.cpp) units.
Но свободныйstatic функционировать вnamespace/ global scope имеет разные копии на каждую единицу перевода.

например

// file.h
static void foo () {}
struct A {
  static void foo () {}
};

// file1.cpp
#include"file.h"
void x1 ()
{
  foo();  // different function exclusive to file1.cpp
  A::foo();  // same function
}

// file2.cpp
#include"file.h"
void x2 ()
{
  foo();  // different function exclusive to file2.cpp
  A::foo();  // same function
}
Если не согласен, в строке бесполезно. Это "только" подсказка, но все же, это подсказка, и компиляторы придают определенную ценность этой подсказке.
Я не понимаю ваш ответ, пожалуйста, подробно опишитеWhat отличается иHow это отличается? Alok Save
Спасибо за разработку. Alok Save
С / Ob1 inline является подсказкой, что функция может быть встроенной. Без пометки как встроенная функция никогда не указывается.
@ Сума, ты имеешь в виду, если ты намекнешь?inline затем MSVS также включает рекурсивный вызов функции (эффект # 1 в OP) с/Ob1? Это невозможно. Могут быть и другие такие случаи, когда функция не будет заменена ее определением (например, тело функции слишком велико и вызывается в разных местах). Там нет значения подсказки. Единственный гарантированный эффектinline это № 2 (из ОП).
11

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

То есть только сstatic inline вы действительно можете заменить использование макроса,inline само по себе не достаточно.

Простой поиск в Google по запросу "статическая строка" покажет вам страницы документации компилятора, которые говорят об этом. Полагаю, этого должно быть достаточно, чтобы ответить на ваш вопрос и сказать: «Нет, это практически не бесполезно». Вот один пример сайта, обсуждающего использованиеinlineи конкретноstatic inline http://www.greenend.org.uk/rjk/tech/inline.html

Интересно ваше предложение использоватьstatic inline в качестве замены для макросов специально рекомендуется под этимlinux kernel style guide, («Статические встроенные функции значительно предпочтительнее макросов. Они обеспечивают безопасность типов, не имеют ограничений по длине, ограничений по форматированию, а в gcc они такие же дешевые, как макросы».).
ключевое слово inline в C имеет другую семантику, чем C ++. Сложнее иметь встроенные функции с внешней связью в C, потому что вам нужно вручную выбрать модуль перевода / объектный файл, в который помещается не встроенная версия. Я полагаю, что рекомендация использовать статический inline ориентирована на C и в основном основана на удобстве. Предположительно это увеличивает риск дублирования кода в двоичном

Похожие вопросы