2010-06-24 3 views
2

ли она предпочитает, чтобы определить методы инлайн как:C++: собственно встраивание синтаксис

// math.h 
class Math 
{ 
public: 
    inline static int sum(int a, int b) 
    { 
     return a + b; 
    } 
}; 

или

// math.h 
class Math 
{ 
public: 
    static int sum(int a, int b); 
}; 

// math.cpp 
inline int Math::sum(int a, int b); 
{ 
    return a + b; 
} 

и почему? Есть ли разница? Должны ли вы оставить вложение полностью до компилятора? (Я знаю, что это довольно субъективно, но я бы хотел услышать некоторые мнения и причины).

Кроме того, я считаю, что большинство компиляторов будет встроено или не встроено самостоятельно, независимо от наличия или отсутствия ключевое слово inline?

ответ

2

Вложение - полностью до компилятора. Ключевое слово inline, как и старое ключевое слово C register, - это предложение компилятору сделать некоторую оптимизацию.

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

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

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

+0

Соответствующее примечание: компилятор Microsoft позволяет программистам переопределять свой встроенный анализ с помощью '__forceinline' http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx – sbk

+2

Не совсем верно, поскольку функции маркировки как' inline' допускает множество определений в программе. Функции, определенные в классе, помечены как неявно. Но функций, определенных в пространствах имен, нет, поэтому для них необходимо «inline», чтобы они могли быть определены в заголовках. Я думаю, что это намного больше, чем «предложение компилятору». Я согласен с вами в первом пункте: независимо от того, является ли какой-либо вызов встроенным, полностью зависит от компилятора, но это не единственная точка ключевого слова 'inline'. –

+0

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

0

Это не имеет большого значения с точки компилятора, чтобы использовать любой из этих двух методов

Но в целом, его предпочтительным для заголовочные файлы содержат только объявления, так же спецификации класса интерфейс, так что любой желающий может посмотреть в заголовке файл и не нужно вникать в то, как реализована функциональность. Итак, лучше иметь спецификацию интерфейса в файле заголовка и реализацию в .cpp-файле

4

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

class Math { 
public: 
    static int sum(int a, int b) // inlined even without 'inline' 
     { return a+b; } 
}; 

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

2

Проблема, связанная с использованием второго метода, заключается в том, что при компиляции других исходных файлов, которые включают math.h, они не будут знать определения вашей функции Math::sum. Поэтому они не смогут его встроить.

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

+3

Я использовал вас здесь, но компиляторы теперь могут выполнять оптимизацию по единицам перевода. В VS полная программная оптимизация, в LLVM флаг -O4 связывает оптимизацию времени, и я верю (не уверен здесь), что gcc также выполняет некоторую вставку, не видя фактического кода. –

1

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

// math.h 
class Math 
{ 
public: 
    static int sum(int a, int b); 
}; 

// At the very end of math.h 
#ifndef _DEBUG 
#include "math.inline.h" 
#endif 

// math.inline.h 
#ifdef _DEBUG 
#define INLINE 
#else 
#define INLINE inline 
#endif 

INLINE int Math::sum(int a, int b); 
{ 
    return a + b; 
} 

// math.cpp 
#include "math.h" 
#ifdef _DEBUG 
#include "math.inline.h" 
#endif 

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

+0

Если это действительно делает разницу в производительности в эти дни (с привязкой времени ссылки), почему бы просто не пропустить math.inline.h и выполнить трюк в math.cpp напрямую? –

+0

Во-первых, у нас есть довольно старая кодовая база. Во-вторых, вы зависите от своего компилятора, чтобы иметь возможность встроенных функций, реализованных в файле .cpp; это, по крайней мере, связано с переносимостью. Я думаю, что наш подход прост и работает с любым компилятором. – Gorpik

+0

.. но это куча работы по написанию и обслуживанию. Стоит ли оно того? – JBRWilkinson

0

Компиляторы обычно могут перемещать код между единицами перевода, поэтому они не должны иметь разницы. Лично я предпочитаю это (все в заголовке):

// math.h 
class Math 
{ 
public: 
    static int sum(int a, int b); 
}; 

inline int Math::sum(int a, int b) 
{ 
    return a + b; 
} 

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

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

В качестве важного примечания, довольно часто обнаруживается, что вложение не оказывает заметного улучшения в производительности, и есть много случаев, когда неинъекционный код лучше, чем его вложение. Я нашел, что это даже относится к простым функциям доступа к одной линии: только потому, что код, когда он встроен, требует меньше инструкций, чем для вызова функции, не всегда означает, что компилятор будет работать с ним лучше. Over-inlining может на самом деле путать компиляторы (например, не используя регистры очень эффективно из-за слишком большого количества встроенного, исключительного кода доступа к памяти). Вложение действительно должно выполняться с осторожностью и помощью профилировщика.

0

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

1

Ваш второй путь будет сделать что не ЕП, кроме math.cpp разрешается называть Math::sum, потому что стандарт говорит, что встроенные функции должны быть определены в каждом переводе единицы, в которой они используются. Вполне возможно, что это приведет к ошибке времени соединения (я столкнулся с этой проблемой раньше).

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

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