Методы класса C ++, определенные в заголовке, всегда встроены? - PullRequest
9 голосов
/ 06 декабря 2011

Редактировать : я восстановил исходный заголовок, но на самом деле я должен был спросить: «Как компоновщики C ++ обрабатывают методы класса, которые были определены в нескольких объектных файлах»

Скажем, у меня есть класс C ++, определенный в заголовке в следующих строках:

class Klass
{
    int Obnoxiously_Large_Method()
    {
        //many thousands of lines of code here
    }
}

Если я скомпилирую код C ++, который использует Obnoxiously_Large_Method в нескольких местах, получится ли полученный объектный файлвсегда вставляйте код для Obnoxiously_Large_Method или он будет оптимизирован по размеру (например, при использовании g ++ -O) и создайте один экземпляр Obnoxiously_Large_Method и используйте его как обычную функцию ?, если да, как компоновщики разрешаютконфликты между другими объектными файлами, которые создали ту же функцию?Есть ли какое-то загадочное пространство имен C ++ Juju, которое не позволяет отдельным экземплярам объекта метода сталкиваться друг с другом?

Ответы [ 6 ]

11 голосов
/ 06 декабря 2011

7.1.2 Спецификаторы функций

Объявление функции (8.3.5, 9.3, 11.4) со встроенным спецификатором объявляет встроенную функцию.Встроенный спецификатор указывает реализации, что внутренняя замена тела функции в точке вызова должна быть предпочтительнее обычного механизма вызова функции.Реализация не требуется для выполнения этой внутренней замены в точке вызова;однако, даже если эта встроенная подстановка опущена, другие правила для встроенных функций, определенные в 7.1.2, все равно должны соблюдаться.

Таким образом, компилятору не требуется фактически «встроить» какую-либо функцию.

Однако в стандарте также сказано:

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

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

4 голосов
/ 06 декабря 2011

Раздел [9.3], Функции-члены, Стандарт C ++ 98 гласит:

Функция-член может быть определена (8.4) в своем определении класса, в этом случае это встроенная функция-член (7.1.2).

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

В спецификаторе функции inline Стандарт гласит:

Объявление функции (8.3.5, 9.3, 11.4) со спецификатором inline объявляет встроенную функцию .Встроенный спецификатор указывает [компилятору C ++], что внутренняя замена тела функции в точке вызова предпочтительнее обычного механизма вызова функции.[Тем не менее, компилятор C ++] не требуется для выполнения этой внутренней подстановки в точке вызова;

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

4 голосов
/ 06 декабря 2011

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

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

2 голосов
/ 06 декабря 2011

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

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

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

Это сказалоРаньше я работал с компилятором greenhills, и он фактически подчинялся моей воле больше, чем не слушался :) .. Это на самом деле зависит от компилятора.

1 голос
/ 06 декабря 2011

Ключевое слово inline относится к определению функции на языке c ++.Компилятор может встроить объектный код в любое место.

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

Подробнее см. этот ответ .

1 голос
/ 06 декабря 2011

Не нужно указывать, нет;это как если бы вы указали inline явно.

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

...