#c #performance
#c #Производительность
Вопрос:
У меня есть простой класс:
class A {
public:
int get() const;
private:
void do_something();
int value;
}
int A::get() const {
return value;
}
Функция получения проста и понятна. Геттеры должны использовать их, поэтому в do_something я должен использовать get()
для доступа value
. Мой вопрос: будет ли компилятор оптимизировать геттер, чтобы это было эквивалентно прямому доступу к данным? Или я все равно получу производительность, если получу к нему прямой доступ (что будет означать худший дизайн)?
A::do_something()
{
x = get();
// or...
x = value;
}
Комментарии:
1. Реальный вопрос, конечно, таков: имеет ли это значение ? Потому что, если это не так, то кого это волнует? И если это так, то только вы можете проверить, выполняет ли оптимизацию ваш конкретный компилятор.
Ответ №1:
Когда метод не является виртуальным, компиляторы могут его оптимизировать. Хорошие компиляторы (с оптимизацией времени соединения) могут оптимизировать, даже если метод не inline
определен и определен в отдельном файле .cpp. Не очень хорошие могут сделать это, только если оно объявлено внутри определения класса или в заголовочном файле с inline
ключевым словом. Для виртуальных методов это зависит, но, скорее всего, нет.
Комментарии:
1. приятно упомянуть
virtual
об этом.2. Для виртуальных функций это зависит от того, знает ли компилятор динамический тип или нет. Хотя наиболее частое использование виртуальных функций приводит к контекстам, в которых это невозможно, существуют исключения, и я знаю по крайней мере одну идиому, которая зависит от компилятора, встраивающего виртуальные функции.
Ответ №2:
Компилятор почти наверняка встроит такое тривиальное средство получения, если у него есть доступ к определению.
Комментарии:
1. Будет ли это встроенным средством получения без
inline
ключевого слова, определив его вне класса?2. @ks1322: определение функций-членов в классе неявно объявляется как
inline
.3. @Nawaz, я спрашиваю, будет ли оно встроено в данном конкретном случае (
inline
ключевое слово отсутствует, функция-член определена вне класса)?4. @ks1322, это зависит от качества компилятора. Visual Studio встроит функцию в конфигурацию выпуска по умолчанию.
5. @ks1322: Многие современные компиляторы теперь имеют компоновщики, которые могут быть встроенными, включая Visual Studio и GCC.
Ответ №3:
Если средство получения определено как встроенная функция (либо неявно, определяя его внутри класса, либо явно с inline
помощью ключевого слова), компилятор обычно встроит его, и при его вызове не будет накладных расходов.
Однако для отладочных сборок обычно отключается встраивание, что вполне допустимо, поскольку компиляторы не обязаны ничего встраивать.
Ответ №4:
Ну, использование get обычно является лучшим дизайном, потому что оно скрывает фактическую логику, связанную с получением значения (сегодня это поле, завтра может потребоваться более сложная логика). Что касается производительности, хотя доступ к самому значению всегда будет по крайней мере таким же быстрым, как при использовании get , компилятор, скорее всего, все равно встроит вызов.
Ответ №5:
Во-первых, вы не сможете манипулировать значением внутри вашего объекта, если вы не возвращаете ссылку, а не значение:
intamp; get();
Теперь он возвращает ссылку и может быть изменен. Но имхо это не совсем чисто, вы также должны определить средство установки и использовать его для записи измененного значения:
int get() const;
void set(int);
...
A::do_something()
{
x = get();
set(value);
}
Производительность средства установки зависит от вашего компилятора. Большинство современных компиляторов способны встроить простые геттеры / сеттеры, поэтому потери производительности не должно быть.