Встроенный метод: внутри или вне определения класса

18

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

class Vector {
private:
    double* data_;
    double* size_;
    double* capacity_;
public:
    double& operator[](int k) {
        return data_[k];
    }
    ...
}

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

class Vector {
private:
    double* data_;
    double* size_;
    double* capacity_;
public:
    inline double& operator[](int k);
    ...
}

double& Vector::operator[](int k) {
    return data_[k];
}

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

Итак, мой вопрос заключается в следующем. Есть ли у текущих компиляторов (я имею в виду GCC , Clang , Intel и Visual Studio ) чаще всего включают встроенную функцию-член, которая объявлено внутри класса, чем функция-член, объявленная вне класса с ключевым словом inline?

Примечание. Этот вопрос не является дубликатом Когда я должен написать ключевое слово" inline "для функции / метода? , так как мой вопрос касается реализаций компилятора. Сделайте эти два способа сказать, что вы хотите, чтобы эти функции были встроены эквивалентны. То, как написано STL, предполагает, что это не так.

    
задан InsideLoop 09.03.2015 в 11:21
источник
  • Возможный дубликат stackoverflow.com/questions/1759300/... –  dhke 09.03.2015 в 11:33

3 ответа

13

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

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

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

Мой совет: используйте то, что вы считаете более читабельным, поскольку это не повлияет на фактическое встраивание (если вы не используете что-то специфичное для компилятора, например __forceinline (не делайте этого)).

    
ответ дан Motti 09.03.2015 в 11:40
  • Спасибо за то, что функция не встроена. Вызов функции является встроенным. Но ключевое слово C ++ inline неплохо применяет эту путаницу. –  InsideLoop 09.03.2015 в 11:43
  • Спасибо за подсказку об использовании inline, которые не дают ошибок в определении нескольких определений. Но он по-прежнему не объясняет, почему разработчики STL по-прежнему используют встроенные шаблонные классы. –  InsideLoop 09.03.2015 в 11:46
  • Шаблонные методы должны быть видимыми в точке использования / создания экземпляра, что означает помещать их в заголовок где-то. Таким образом, выбор - это просто определить метод, буквально встроенный в ваш класс, или предоставить встроенное объявление и определить его позже (но все еще в заголовке). Это стилистический выбор и не имеет никакого отношения к вашему вопросу о вероятности встраивания на сайтах вызовов. –  Useless 09.03.2015 в 12:29
  • @Motti: существует разница между «встроенными функциями» на уровне языка и функциями, которые встроены в компилятор. Методы, определенные в классе или с ключевым словом inline, являются встроенными методами для компилятора. Компилятор часто не вставляет код для таких методов в точку вызова, но они могут делать это для методов, которые не являются встроенными. Компилятор может даже частично встроить (например, встроенная рекурсивная факториальная функция может встроить вызовы на четыре уровня в глубину, а затем называть себя рекурсивно). –  gnasher729 09.03.2015 в 16:52
  • @ gnasher729 уверен, но исторически цель ключевого слова inline заключалась в том, чтобы сообщить компилятору, что разработчик хочет, чтобы эта функция была встроена. Как только компиляторы продвинулись достаточно, чтобы сделать эту избыточность, она осталась (как @AndyBrown) в качестве модификатора компоновщика. Это похоже на то, как утверждает Херб Саттер, что const теперь означает потокобезопасность. –  Motti 09.03.2015 в 20:52
6

Do current compilers (I am thinking of gcc, clang, Intel, Visual Studio) are more likely to inline a member function that is declared inside the class than a member function declared out of class with the inline keyword?

Это не имеет абсолютно никакого значения.

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

    
ответ дан Andy Brown 09.03.2015 в 11:52
  • Я понимаю, что современные компиляторы игнорируют его. Но почему библиотека libc ++ имеет _LIBCPP_INLINE_VISIBILITY, определяет какой-то метод в классе и другие вне класса? Это, кажется, очень сложный способ делать вещи. –  InsideLoop 09.03.2015 в 12:00
  • @InsideLoop - Это связано с необходимостью корректировать видимость ELF встроенных строк при создании libc ++ в качестве DSO, чтобы вы не заканчивали определениями из разных общих объектов, которые используют libc ++, столкнувшись друг с другом во время выполнения. –  LThode 09.03.2015 в 13:54
  • @LThode: Спасибо за вашу информацию. –  InsideLoop 09.03.2015 в 14:30
  • Как минимум gcc в некоторой степени выполняет поиск ключевого слова inline. Вы абсолютно уверены, что позиция определения функции не имеет никакого влияния? –  MikeMB 05.12.2016 в 09:05
1

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

    
ответ дан Luchian Grigore 09.03.2015 в 11:33