Геттеры и сеттеры. Есть ли накладные расходы на производительность?
У меня есть механизм Particle System Engine в моем проекте на С++, и сами частицы - это просто структуры переменных без функций. В настоящее время каждая частица (Particle) обновляется из своего родительского класса (ParticleSystem) путем прямого доступа к своим переменным. Например.
particle.x += particle.vx;
Тем не менее, я обсуждаю использование геттеров и сеттеров следующим образом:
particle.setX( particle.getX()+particle.getVX() );
Мой вопрос: есть ли накладные расходы на производительность при вызове getters и seters, а не только прямому доступу к данным?
В конце концов, у меня есть много многих частиц для обновления через...
Ответы
Ответ 1
У сеттеров и геттеров есть служебные служебные данные , если они не оптимизированы. Они почти всегда оптимизированы для компиляторов, которые связывают оптимизацию времени. А на компиляторах, которые этого не делают, если у них есть знание о теле функции (то есть не только прототипе), оно будет оптимизировано.
Однако вы используете геттеры и сеттеры, потому что вам может понадобиться получить или установить для этой переменной дополнительные побочные эффекты. Подобно изменению положения объекта, также изменяется положение соседних объектов в физическом моделировании или некоторые из них.
Наконец, накладные расходы на работу геттера и сеттера в контексте оптимизированного кода очень малы, не стоит беспокоиться, если код не горячий. И если он горячий, это ТАК ЛЕГКО просто перемещать геттер или сеттер в файл заголовка и встраивать его.
Итак, чтобы подвести итог, геттеры и сеттеры хорошо стоят второстепенных или несуществующих накладных расходов, так как это позволяет вам конкретно указать, что может и не может произойти с вашим объектом, а также позволяет маршировать любые изменения.
Ответ 2
У меня другое мнение, чем предыдущие ответы.
Getters и seters являются признаками того, что ваш класс не разработан полезным образом: если вы не делаете внешнее поведение абстрактным из внутренней реализации, нет смысла использовать абстрактный интерфейс в первую очередь, вы можете а также использовать простую старую структуру.
Подумайте, какие операции вам действительно нужны. Это почти наверняка не прямой доступ к x-y- и z-координатам положения и импульса, вы скорее хотите рассматривать их как векторные величины (по крайней мере, в большинстве расчетов, что все, что имеет значение для оптимизация). Таким образом, вы хотите реализовать векторный интерфейс *, где основными операциями являются векторное сложение, масштабирование и внутренний продукт. Не компонентный доступ; вам, вероятно, также нужно делать это иногда, но это можно сделать с помощью одного члена std::array<double,3> to_posarray()
или что-то в этом роде.
Когда внутренние компоненты x
, y
... vz
недоступны извне, вы можете безопасно изменить внутреннюю реализацию, не торгуя никаким кодом вне вашего модуля. Это в значительной степени все зависит от геттеров/сеттеров; однако при использовании этих возможностей существует только такая оптимизация, которую вы можете сделать: любое реальное изменение реализации с неизбежностью делает геттеры намного медленнее.
С другой стороны, вы можете оптимизировать ад из векторного интерфейса, с SIMD-операциями, внешними вызовами библиотеки (возможно, на ускоренном оборудовании, например CUDA) и т.п. "Batch-getter", например, to_posarray
, все еще может быть реализован достаточно эффективно, установки с одной переменной не могут.
* Я имею в виду вектор в математический смысл, а не как std::vector
.
Ответ 3
Getters и seters позволяют вашему коду развиваться более легко в будущем, если получение и настройка оказываются несколько более сложными задачами. Большинство компиляторов С++ достаточно интеллектуальны для inline этих простых методов и устраняют накладные расходы на вызов функции.
Ответ 4
На этот вопрос могут быть ответы на разные вопросы, но я тут же придумываю свои мысли.
Для производительности стоимость может быть в основном проигнорирована для простого типа POD.
Но все равно стоит, и это зависит от того, какой тип вы вернетесь. Для частиц не могло быть много данных. Если это класс изображения (например, OpenCV cv:: Mat) или 3d-данные (например, PolyData в VTK), лучше, чтобы setter/getter работал с указателями/итераторами, чем с фактическими данными, чтобы избежать проблемы с распределением памяти.
Если вы хотите создавать шаблоны, то сеттер/получатель может быть полезным, чтобы избежать неявного преобразования типов. Сеттер/получатель может быть способом доступа к частному/защищенному элементу, что также позволяет избежать использования x в качестве общего имени переменной. Более того, setter/getter может возвращать ссылку Lvalue, которая позволяет вам делать particle.getX() = 10.0 ;