Подтвердить что ты не робот

Почему нет стандартного способа принудительного inline в С++?

В соответствии с статья Википедии С++

С++ предназначен для выбора программиста, даже если это позволяет программисту неправильно выбирать.

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

Или я могу спросить, почему ключевое слово inline - это просто подсказка?

Думаю, у меня нет выбора.

В мире ООП мы вызываем методы на объектах, и следует избегать прямого доступа к членам. Если мы не можем заставить аксессоров быть встроенными, тогда мы не сможем писать высокопроизводительные, но все же поддерживаемые приложения.

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

Компилятор всегда делает это лучше, чем программист?

4b9b3361

Ответ 1

Как компилятор встроил бы рекурсивную функцию (особенно если компилятор не поддерживает оптимизацию Tail-call, и даже если это произойдет, функция не будет оптимизирована для Tail-call).

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

Ответ 2

Компилятор всегда делает это лучше, чем программист?

Нет, не всегда... но программист гораздо более подвержен ошибкам и с меньшей вероятностью поддерживает оптимальную настройку в течение нескольких лет. Суть в том, что вложение только помогает производительности, если функция действительно мала (по крайней мере для одного общего/важного кода), но тогда она может помочь примерно на порядок, в зависимости от многих вещей, конечно. Часто нецелесообразно оценивать программиста, не говоря уже о том, чтобы внимательно следить за тем, насколько тривиальна функция, а пороговые значения могут варьироваться в зависимости от вариантов реализации компилятора, параметров командной строки, модели процессора и т.д. Есть так много вещей, которые могут внезапно раздуваться функция - любой не встроенный тип может инициировать всевозможные типы поведения (esp в шаблонах), использование оператора (даже new) может быть перегружено, многословие вызовов и шаги обработки исключений обычно не очевидны для программист.

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

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

Ответ 3

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

Потому что вы "можете" знать лучше, чем компилятор.

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

Например, большинство компиляторов автоматически встраивают функции-члены, которые полностью определены в заголовке, если код не длинный и/или слишком сложный. Это потому, что, поскольку функция доступна в заголовке, почему бы не встроить ее как можно больше? Однако этого не происходит, например, в режиме Debug для Visual Studio: в Debug информация об отладке по-прежнему должна отображать двоичный код функций, поэтому избегайте встраивания, но все равно встроенные функции, помеченные как встроенные, поскольку пользователю требуется Это. Это полезно, если вы хотите отмечать функции yuo, не нужно иметь информацию о времени отладки (например, простые геттеры), получая более высокую производительность во время отладки. В режиме деблокирования (по умолчанию) компилятор будет агрессивно встраивать все, что он может, затрудняя отладку некоторой части кода, даже если вы активируете информацию для отладки.

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

Поскольку вложение зависит от обоих контекстов вызывающего и вызываемого, нет "правила". Часто рекомендуется просто игнорировать явную маркировку функции inline, но в двух случаях:

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

Всегда ли компилятор делает это лучше чем программист?

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

Ответ 4

Ошибочное предположение.

Есть способ. Он записал #define. И для многих ранних проектов C это было достаточно хорошо. inline был достаточно различным - подсказка, лучшая семантика - что она может быть добавлена ​​помимо макросов. Но как только у вас были оба, осталось немного места для третьего варианта между ними, один с лучшей семантикой, но не факультативный.

Ответ 5

Если вам действительно нужно заставить встроенную функцию (почему?), вы можете сделать это: скопируйте код и вставьте его или используйте макрос.