Методы в прыще встроены? - PullRequest
3 голосов
/ 06 июня 2011

Рассматривая следующий простой пример:

Заголовок:

// a.hpp
#ifndef A_HPP
#define A_HPP
#include <memory>

class A
{
 public:
  A();

  int foo();

 private:
  struct Imp;
  std::auto_ptr< Imp > pimpl;
};

#endif // A_HPP

Реализация:

// a.cpp
#include "a.hpp"

struct A::Imp
{
 int foo()
 {
  // do something and return the result
 }
};

A::A() : pimpl( new Imp )
{}
int A::foo()
{
  return pimpl->foo();
}

Основное:

// main.cpp
#include "header.hpp"
int main()
{
  A a;
  return a.foo();
}

Вопросы:
Будет ли метод A::Imp::foo встроен в A::foo?
Зависит ли это от реализации, которая находится в этом методе?

PS Я использую gcc (4.3.0, если это имеет значение).

EDIT

Полагаю, я не очень хорошо объяснил.Что я имел в виду именно это.Если я использую максимальный уровень оптимизации, будет ли // do something and return the result помещаться в A::foo() или A::Imp::foo()?
Без оптимизации я вижу, что это не сделано (по-прежнему вызывается the pimpl->foo()).

Я понимаю, что A :: foo () никогда не будет встроен в main (), но я не об этом спрашиваю.

Ответы [ 2 ]

10 голосов
/ 06 июня 2011

Все вставки зависят от реализации. Если это важно для вас, посмотрите на испущенный код ассемблера.

8 голосов
/ 06 июня 2011

Херб Саттер однажды сделал отличную статью о встраивании.

Первый вопрос, который нужно задать: когда может произойти встраивание?

В C ++:

  • это может произойти на этапе компиляции
  • это может произойти на этапе соединения (LTO: оптимизация времени соединения)

Оба раза механизм аналогичен: если компилятор / компоновщик знает о реализации метода, он может решить скопировать / вставить реализацию вместо вызова вызова. Это решение основано на сложной эвристике, и я знаю только, что они существуют, а не то, о чем они.

Поэтому критическая точка знает о реализации бит.

  • для компилятора: это означает, что определено в той же единице перевода
  • для компоновщика: это означает, что он определен в одном из связанных модулей перевода ИЛИ в статической библиотеке, с которой он будет связан ... afaik он не будет оптимизирован, если метод находится в DLL

Так здесь : да, звонок pimpl->foo() может быть встроен в A::foo. Это будет зависеть как от компилятора , так и от параметров компиляции.

Для gcc / clang, если A::Impl::foo достаточно мало, его можно оптимизировать с O1 и далее (если вы не передадите -fno-inline).

...