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

Пытается ли теперь (нормальный) компилятор встроить все функции? Есть ли какие-либо преимущества в определении встроенных функций-членов как inline на практике (см. Пример ниже)? Следует ли мне теперь избегать написания встроенных функций даже в шаблонах?

template <class Foo>
struct Bar {
    inline bool IsThereBenefitInDoingThis()
    {
        return 10 < system("exit `wget -q -o - "
            "http://stackoverflow.com/questions/23789353/ | grep yes | wc -l`");
    }
};
2
the swine 21 Май 2014 в 20:50

2 ответа

Лучший ответ

Простой тест:

#include <math.h>
#include <stdio.h>

template <class T>
class Sine {
public:
#ifdef MAKEINLINE
    inline T Eval(T x)
#else // MAKEINLINE
    T Eval(T x)
#endif // MAKEINLINE
#ifdef PUTOUTSIDE
    ;
#else // PUTOUTSIDE
    {
        return T(sin(double(x)));
    }
#endif // PUTOUTSIDE
};

#ifdef PUTOUTSIDE
template <class T>
#ifdef MAKEINLINE
inline T Sine<T>::Eval(T x)
#else // MAKEINLINE
T Sine<T>::Eval(T x)
#endif // MAKEINLINE
{
    return T(sin(double(x)));
}
#endif // PUTOUTSIDE

int main(int argc, const char **argv)
{
    printf("%g\n", Sine<float>().Eval(M_PI));
    printf("%g\n", Sine<double>().Eval(M_PI));
    return 0;
}

Бег:

g++ Main.cpp -o testi -DMAKEINLINE -O1
g++ Main.cpp -o testn -O1
g++ Main.cpp -o testo -DPUTOUTSIDE -O1
g++ Main.cpp -o testoi -DMAKEINLINE -DPUTOUTSIDE -O1
diff testi testn
diff testi testo
diff testi testoi

Обнаруживает разницу между testi и testo, поэтому, пока тело находится внутри, не имеет значения, объявлено ли оно inline или, по крайней мере, в этом простом случае и в g ++ (GCC) 4.6.4. Обратите внимание, что при увеличении уровня оптимизации встраиваются все версии функции и нет никаких различий.

1
BenMorel 15 Сен 2014 в 07:45

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

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

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

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

1
Steve314 15 Сен 2014 в 08:06