Интернет, компьютеры, софт и прочий Hi-Tech

Подписаться через RSS2Email.ru

Страница 3 из 10 - Предыдущая - Следующая
Все страницы - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10

Краткий FAQ по C++

РАЗДЕЛ [9]: Встроенные (inline) функции

[9.1] Что такое встроенная функция?

Встроенная функция - это функция, код которой прямо вставляется в том месте, где она вызвана. Как и макросы, определенные через #define, встроенные функции улучшают производительность за счет стоимости вызова и (особенно!) за счет возможности дополнительной оптимизации ("процедурная интеграция").

[9.2] Как встроенные функции могут влиять на соотношение безопасности и скорости?

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

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

Стоимость вызова функции невелика, но дает некоторую прибавку. Классы С++ позволяют встраивание функций, что дает вам безопасность инкапсуляции вместе со скоростью прямого доступа. Более того, типы параметры встраиваемых функций проверяются компилятором, что является преимуществом по сравнению с (?)сишными #define макросами.

[9.3] Зачем мне использовать встроенные функции? Почему не использовать просто #define макросы?

Поскольку #define макросы опасны [9.2], опасны [34.1], опасны [34.2], опасны [34.3].

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

    // Макрос, возвращающий модуль (абсолютное значение) i
    #define unsafe(i) \
        ( (i) >= 0 ? (i) : -(i) )

    // Встроенная функция, возвращающая абсолютное значение i
    inline
    int safe(int i)
    {
        return i >= 0 ? i : -i;
    }

    int f();

    void userCode(int x)
    {
        int ans;
        ans = unsafe(x++); // Ошибка! x инкрементируется дважды
        ans = unsafe(f()); // Опасно! f() вызывается дважды
        ans = safe(x++); // Верно! x инкрементируется один раз
        ans = safe(f()); // Верно! f() вызывается один раз
    }

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

Макросы вредны для здоровья; не используйте их, если это не необходимо

[9.4] Что сделать, чтобы определить функцию - не член класса как встроенную?

Когда вы объявляете встроенную функцию, это выглядит как обычное объявление функции:

    void f(int i, char c);

Но перед определением встроенной функции пишется слово inline, и само определение помещается в заголовочный файл:

    inline
    void f(int i, char c)
    {
        // ...
    }

Примечание: Необходимо, чтобы определение встроенной функции (часть между {...}) была помещена в заголовочный файл, за исключением того случая, когда функция используется только в одном .cpp файле. Если вы помещаете определение встроенной функции в .cpp файл, а вызываете ее из другого .cpp файла, то вы получаете ошибку "unresolved external" ("ненайденный внешний объект") от компоновщика (linker).

(Примечание переводчика: На всякий случай уточню, что само помещение определения функции в заголовочный файл НЕ делает ее встроенной. Это требуется только для того, чтобы тело функции было видно во всех местах, где она вызывается. Иначе невозможно обеспечить встраивание функции. - YM)

Страница 3 из 10 - Предыдущая - Следующая

Биржа долевых инвестиций SIMEX.

Последнее редактирование: 2009-10-02 15:35:36

Метки материала: C++, FAQ, программирование, встроенные функции, inline, функции, встроенная функция, макросы, функция, define, производительность, оптимизация, процедурная интеграция, C, инкапсуляция, void, класс, заголовочный файл, cpp, определение функции

Оставьте, пожалуйста, свой комментарий к публикации

Представиться как     Антибот:
   

Просьба не постить мусор. Если вы хотите потестить xBB, воспользуйтесь кнопкой предварительного просмотра на панели инструментов xBBEditor-а.


© 2007-2019, Дмитрий Скоробогатов.
Разрешается воспроизводить, распространять и/или изменять материалы сайта
в соответствии с условиями GNU Free Documentation License,
версии 1.2 или любой более поздней версии, опубликованной FSF,
если только иное не указано в самих материалах.