Код в заголовочных файлах всегда будет встроен? - PullRequest
14 голосов
/ 27 июля 2010

Я только что обсудил с коллегой код в заголовочных файлах:

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

MyClass.hpp

   class MyClass
    {
    public:
    MyClass();
    ~MyClass();

    int GetNumber() const 
    {
     //...; 
     return m_number;
    };

    private:
    int m_number;
    };

Ответы [ 7 ]

12 голосов
/ 27 июля 2010

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

Большинство современных компиляторов обрабатывают inline как связькоманда и не более того.Некоторые компиляторы предоставляют более сильные ключевые слова, такие как CL __forceinline, что означает «встроить это, если это возможно».

Так что вы оба правы и оба в какой-то степени неправы.

7 голосов
/ 27 июля 2010

Ваш приятель не прав, вы правы.

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

Попробуйте запустить препроцессор gcc, тогда вы увидите:

gcc -E some_source_file_with_includes
4 голосов
/ 27 июля 2010

На самом деле оба верны. То, как вы, ребята, имели в виду, немного отличается. ( Я думаю)

Из стандартного документа C ++ для встроенной функции,

  1. Объявление функции (8.3.5, 9.3, 11.4) со встроенным спецификатором объявляет встроенную функцию.

2. Функция, определенная в классе определение является встроенной функцией.

Итак, как сказал ваш коллега, это действительно встроенная функция .

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

Надеюсь, это прояснит ваше беспокойство ..

3 голосов
/ 27 июля 2010

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

2 голосов
/ 27 июля 2010

Функция-член класса, определенная (в отличие от объявленного ), в определении класса неявно inline.Другого кода в заголовках нет.

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

void print(std::ostream& os)
{
  os << "Hello, world!\n";
}

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

Однако есть еще несколько нарушений.Например, определение константы автоматически получит внешнюю связь.Следовательно,

const int answer = 42;

в заголовке не заставит компоновщика жаловаться на множественные определения answer, тогда как

int question;

.

1 голос
/ 27 июля 2010

Компилятор решает. Даже использование _inline только говорит компилятору, что вы предпочитаете встроенный код, но анализатор затрат / выгод компилятора может принять иное решение.

Вы можете использовать _forceinline, если вы используете Microsoft C ++ , чтобы сделать код встроенным, но это может привести к увеличению двоичных файлов.

1 голос
/ 27 июля 2010

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

...