public:
inline int GetValue() const {
return m_nValue;
}
inline void SetValue(int nNewValue) {
this -> m_nValue = nNewValue;
}
На Изучают C++, они сказали, что он будет работать быстрее. Так, я думал, что будет замечательно использовать на методах считывания и методах set. Но возможно, существуют некоторые недостатки к нему?
Я ничего не встраиваю, пока профилировщик специально не скажет мне, что отсутствие встраивания приводит к проблемам с производительностью.
Компилятор C ++ очень умен и почти наверняка автоматически встроит такую простую функцию, как эта. И, как правило, он умнее вас и гораздо лучше определяет, что следует или не следует встраивать.
Я бы не стал думать о том, что нужно или не вставлять, и сосредоточился на решении. Добавление ключевого слова inline
позже (что не является гарантией встроенного BTW) очень легко сделать, и потенциальные места можно легко найти с помощью профилировщика.
Код будет компилироваться немного дольше, и вы потеряете инкапсуляцию. Все зависит от масштабов проекта и его характера. В большинстве случаев можно сделать их встроенными, если в них нет сложной логики.
Кстати, вы можете пропустить встроенный
, если вы реализуете непосредственно в определении класса.
Это плохая практика в общедоступных API. Любое изменение этих функций требует перекомпиляции всех клиентов.
В целом наличие геттеров и сеттеров демонстрирует плохую абстракцию, не делайте этого. Если вы постоянно переходите к необработанным данным в другом классе, вам, вероятно, придется переупорядочить свои классы, вместо этого подумайте, как вы хотите манипулировать данными внутри класса, и предоставьте для этого соответствующие методы.
Если вы напишете их внутри определения, они будут считаться встроенными
по умолчанию .
Это означает, что они будут разрешены в нескольких модулях компиляции (поскольку сами определения классов обычно появляются в нескольких модулях компиляции), не , что они фактически будут встроенными.
Отрицательные моменты:
Компилятор может вас игнорировать.
Любое изменение этих функций требует перекомпиляции всех клиентов.
Хороший компилятор в любом случае будет встраивать невстроенные функции, когда это необходимо.
Я бы сказал, что вам не нужно об этом беспокоиться. Прочтите раздел часто задаваемых вопросов о встраивании .
Помещая код в заголовок, вы раскрываете свою внутреннюю работу класса. Клиенты могут это увидеть и сделать предположения о том, как работает ваш класс. Это может затруднить последующее изменение вашего класса без нарушения клиентского кода.
Я также хотел бы добавить, что если вы не выполняете миллионы get/set на кадр, то практически не имеет значения, инлайнятся они или нет. Честно говоря, не стоит из-за этого терять сон.
Кроме того, имейте в виду, что если вы поставили слово 'inline' перед декларацией+определением, это не значит, что компилятор будет инлайнить ваш код. Он использует различные эвристики, чтобы определить, имеет ли это смысл, что часто является классическим компромиссом между скоростью и размером. Однако есть ключевое слово '__forceinline', которое используется в VC++ (я не уверен, что оно есть в GCC), которое перечеркивает эвристику компилятора. Я действительно не рекомендую это делать, и, кроме того, когда вы перейдете на другую архитектуру, это, скорее всего, будет неправильно.
Постарайтесь поместить все определения функций в файл реализации, а чистые декларации оставьте для заголовков (если, конечно, вы не метапрограммируете шаблоны (STL/BOOST/etc), в этом случае почти все будет в заголовках ;))
Одно из классических мест, где люди любят инлайнить (по крайней мере, в видеоиграх, откуда я родом), это математические заголовки. Произведения крестиков/ноликов, длины векторов, очистка матрицы и т.д. часто помещаются в заголовок, что я считаю излишним. В 9/10 случаев это не имеет никакого значения для производительности, и если вам когда-нибудь понадобится сделать узкий цикл, например, преобразовать большой векторный массив по некоторой матрице, вам, вероятно, лучше вручную выполнить математику в строке, или даже лучше закодировать ее на ассемблере для конкретной платформы.
О, и еще один момент, если вы чувствуете, что вам действительно нужно, чтобы класс был больше данными, чем кодом, подумайте об использовании старого доброго struct, который не приносит с собой OO багаж абстракции, для этого он и существует. :)
Извините, не хотел так много говорить, но я просто думаю, что это помогает рассмотреть реальные случаи использования в реальном мире, и не зацикливаться на педантичных настройках компилятора (поверьте мне, я был там ;))
Удачи.
Shane
Не надо, начинайте доверять компиляторам, по крайней мере, для таких оптимизаций!
«Но не всегда»
Должен сказать, я не испытывают сильное отвращение к этой практике, которое, похоже, испытывают другие участники этой беседы. Я согласен с тем, что прирост производительности от встраивания незначителен во всех случаях, кроме наиболее часто используемых. (И да, я встречал такие случаи на практике.) Когда я делаю такой вид встраивания, я делаю это для удобства и обычно только для однострочников, подобных этому. В большинстве моих случаев использования необходимость избегать перекомпиляции на стороне клиента, если я когда-либо их изменяю, просто не так уж сильна.
Да, вы можете удалить встроенный
, поскольку это подразумевается размещением реализации.
Кроме того, я немного удивлен яростным отношением к аксессуарам. Вы вряд ли сможете чихнуть в классе на любом объектно-ориентированном языке, не взорвав нескольких, и, в конце концов, это действенный метод абстрагирования реализации от интерфейса, поэтому было бы немного мазохистично называть их плохой практикой объектно-ориентированного программирования. Это хороший совет не писать аксессоры без разбора, но я также советую вам не увлекаться рвением по их искоренению.
Возьмите это, пуристы. : -)