Код в файлах заголовков всегда будет встроен?

У меня только что было обсуждение с коллегой по поводу кода в файлах заголовков:

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

MyClass.hpp

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

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

    private:
    int m_number;
    };

Ответы

Ответ 1

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

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

Итак, вы оба правы и оба неправы до степени.

Ответ 2

Твой приятель ошибается, ты прав.

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

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

gcc -E some_source_file_with_includes

Ответ 3

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

Ответ 4

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

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

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

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

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

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

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

Ответ 5

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

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

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

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

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

const int answer = 42;

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

int question;

будет.

Ответ 6

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

Ответ 7

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

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