Имеет ли средство получения нулевую стоимость?

#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);
}
  

Производительность средства установки зависит от вашего компилятора. Большинство современных компиляторов способны встроить простые геттеры / сеттеры, поэтому потери производительности не должно быть.