|
6 / 6 / 4
Регистрация: 13.10.2012
Сообщений: 101
|
|
реализация класса в .h файле хорошо или плохо?17.08.2013, 21:48. Показов 17816. Ответов 61
Метки нет (Все метки)
все знакомые мне ide разделяют класс на два файла: .h с описанием и .cpp с кодом, но, например, в boost .hpp файлы почти всегда содержат и реализацию классов, т.е. так тоже можно. так в чем тогда разница и когда какой способ нужно применять? заранее благодарен
0
|
|
| 17.08.2013, 21:48 | |
|
Ответы с готовыми решениями:
61
Такой способ создание экземпляра класса хорошо или плохо?
Google: хорошо или плохо? |
|
|
|
| 19.08.2013, 18:17 | |
|
Ну почему же? Например, функция LTO в GCC позволяет на несколько процентов уменьшить размер исполняемого файла. Я не вижу смысла использовать эту функцию в мелких проектах, но наоборот, вижу смысл в больших. Ведь LTO не только инлайнит такие методы, но и выполняет другие оптимизации, например такие как удаление неиспользованных функций. Поскольку оптимизация выполняется на уровне линковки, то я не думаю что время сборки в целом увеличится в разы.
0
|
|
|
Ушел с форума
|
|||||
| 19.08.2013, 19:01 | |||||
|
право на существование, которые сертифицированы для использования на космических станциях ? Так можно сказать, что и прекомпилированные заголовки не нужны, и разворачивание циклов, и profile-guided optimization, и т.д. Во-вторых, полезность или вредность данного вида (оптимизации ?) для больших проектов не очевидна. Или поделитесь ссылкой на соответствующие исследования/статистику, или замечание ни о чем. чем хидеры, содержащие частичные определения. Пусть и ценой определенных уступок. А размазывая определения по хидерам и cpp-файлам, можно наступить на мину под названием "нарушение ODR". Особенно в тех самых "больших" проектах. Компилятор прожует и не поморщится. где-то что-то заинлайнить только потому, что у него нет доступа к определению. А вообще, и то и другое попахивает преждевременной оптимизацией.
0
|
|||||
|
|
|||||||
| 19.08.2013, 19:46 | |||||||
|
Пока твой проект состоит из 10 файлов, разница между помодульным режимом в абсолютном времени будет небольшая. В проекте из 1000 файлов - разница будет огромная. Не говоря о том, что режим с межмодульным инлайном по времени работает далеко не линейно по отношению к количеству файлов. Увеличили количество файлов в 2 раза - время компиляции увеличится в 3, 5, 10 или хз сколько раз, но заведомо больше, чем в 2 раза. В противном случае межмодульная часть компилятора попросту работает некачественно 1. (самая главная причина) Опубликовать цифры производительности. Все разработчики (будь то компиляторов, будь-то аппаратуры) публикуют цифры производительности по всяким бенчмаркам. Это стандартный узаконненный способ вешать лапшу на уши пользователям. Т.е. все замеры можно повторить и они покажут те же цифры. Но на реальных задачах (а не на бенчмарках) таких цифр с большой вероятностью не добиться. Режим межмодульного инлайна - ещё одна статья для увеличения цифр производительности, в котором компилятору можно получить бОльшее раздолье для всяких эвристических оптимизаций, которые хорошо ведут себя на бенчмарах, но плохо на реальных задачах 2. (полезная причина) Есть много старого софта, который был написан во времена, когда компиляторы были слабые, а потому никто не задумывался о том, чтобы написать софт правильно. Или программа на Си, в котором не было удобных и эффективных средств по части inline, которые есть на Си++. Может быть, что-то ещё. 3. (маркетинговая причина) Сделать режим для криворуких программистов, которые вообще не понимают (и не хотят понимать), как работает компилятор в первом приближении и как устроены машинные коды. На банере яркими буквами пишется, что, дескать, программируйте и не задумывайтесь ни о чём, наш супер-пупер межмодульный режим сделает вас абсолютно щастливыми
1
|
|||||||
|
Ушел с форума
|
||||||||||
| 19.08.2013, 20:47 | ||||||||||
|
Спрашиваю, потому что написанное выше не соответствует действительности (а может, никогда ей не соответствовало). При IPO повторная компиляция не выполняется. В Visual C++, например, IPO - это некий промежуточный режим между компиляцией, когда код уже перенесен в промежуточное и независимое от процессорной архитектуры представление, и компоновкой. Время сборки увеличивается, но далеко не в такой прогрессии, как Вы указали. Например, беру свой текущий проект: примерно 500 cpp-файлов, сборка под x86/amd64. Общее время сборки порядка 3 минут (на Core-i5 2500). При этом треть этого времени составляет сборка драйверов и компонентов, не относящихся к C++ и IPO. Да, и я имел дело с header-only библиотеками, при подключении которых время сборки увеличивалось чуть ли не на порядок. Не давая, по сути, ничего взамен. Ну кроме простоты сборки, разумеется, это вне вопросов. Как формально (буква "О" в названии говорит сама за себя), так и по факту. Но мы же не формалисты, нас ведь интересует практическое применение, а не навешивание ярлыков ? А знаете, в чем прелесть IPO ? В том, что для его использования не нужно прикладывать никаких усилий. Он просто включен по умолчанию. Думаю, большинство пользователей, особенно начинающих, вообще не знают, что их компилятор использует IPO. И тем не менее, получают все выгоды от него. испытать эту штуку". хидерах оно было бы меньше. При прочих равных условиях. Ну а неудобство... В чем оно ? Я могу писать код в хидерах. А могу в cpp-файлах. И, что хорошо, сгенерированный машинный код будет практически эквивалентным. Где здесь неудобство ? Вижу только одно "неудобство" - программисты, выросшие на современных компиляторах, не знают что такое инлайнинг по своей сути. И как его правильно готовить. Хотя это неудобство - оно для кого ? Для корифеев, которые ноют "вот раньше были времена, а сейчас молодежь не та" ? Ну так может пора ему уже на свалку, этому инлайнингу, раз он не играет существенной роли в оптимизации ? Вы же не сидите с утра до ночи на чемоданах, в ожидании "а вдруг уехать придется" ? Надо будет переходить на другую платформу - будем принимать соответствующие меры. "Всепогодный" код а-ля Boost, который должен работать везде и всегда, нужен лишь в особых случаях, и это обычно оговаривается сразу. Сейчас я живу на Windows, здесь три наиболее ярких компилятора - это Visual C++, Intel C++ и MinGW. Все они поддерживают IPO уже не первый год, поэтому не вижу смысла искать здесь причины, чтобы его не использовать. одного и того же метода в h и cpp. Это не во всех ситуациях отслеживается компилятором, а потом такую ошибку можно искать очень долго. При единообразном подходе (реализация или только в cpp, или только в h) она менее вероятна. это преждевременная оптимизация. Как в случае IPO, так и в случае реализации в хидерах.
0
|
||||||||||
|
|
|
| 19.08.2013, 21:42 | |
|
Не по теме: Я конечно извиняюсь что влезаю в Ваш диалог, но мне, как двоечнику по школе очень интересно, почему англоязычное слово header все переводят (произносят) как хидер ? Добавлено через 32 минуты Не по теме: Меня что, все в "игнор добавили"? Неужели я успел "насолить" всем...
0
|
|
| 19.08.2013, 21:50 | |
|
Не по теме: castaway, англ "e" произноситься как "и"
0
|
|
|
|
|
| 19.08.2013, 22:55 | |
|
Не по теме: Jupiter, на самом деле, нет. В данном слове английская буква 'e' произносится как русская 'э' ( http://ru.forvo.com/word/header/ ). Добавлено через 11 минут Не по теме: Английское слово "head" произносится как "хэд". Английское слово "bread" произносится как "брэд" .. Добавлено через 51 минуту Не по теме: А самое интересное заключается в том, что слово неправильно произносят в шоу "Уральские пельмени": http://www.youtube.com/watch?v=C8Bz9V3JpU0
0
|
|
|
|
||||||||||||
| 19.08.2013, 23:13 | ||||||||||||
|
Моё мнение, что межмодульные режимы - это в том числе и продолжение тех тенденций в погоне за публикуемыми цифрами
0
|
||||||||||||
| 19.08.2013, 23:22 | |
|
Не по теме: Evg, Убежденный, почему бы вам не подружиться?! Мне кажется, из вас вышла бы хорошая команда (заметьте, я специально не поставил "кавычки").
0
|
|
| 19.08.2013, 23:34 | |
|
0
|
|
|
|
|
| 19.08.2013, 23:44 | |
|
У меня даже появилось соображение, почему тот самый межмодульный режим, которым я пользовался давно, был такой медленный. И даже начинаю верить в твои 3 минуты на 500 файлов. Но пока всё равно подозреваю, что межмодульный IPO (в которые входит в том числе и инлайн) будет неглубоким и неагресссивным, но тем не менее небольшой прирост производительности за счёт небольшого увеличения времени компиляции - это однозначно лучше, чем ничего
0
|
|
| 19.08.2013, 23:44 | |
|
0
|
|
|
|
||
| 20.08.2013, 10:14 | ||
|
C++ #include <vector> /* Навесим сюда атрибут noinline, чтобы в обоих последующих * запусках внутренности функции были одними и теми же, * и не зависели от того, как у нас компилятор накрутит цикл * в точке вызова данной функции */ template <typename T> void __attribute__((noinline)) test_copy (const T &lhs, T &rhs) { rhs.clear(); std::insert_iterator<T> ins_it(rhs, rhs.begin()); std::copy(lhs.begin(), lhs.end(), ins_it); } int main (void) { std::vector<int> lhs, rhs; lhs.resize (100000); for (int i = 0; i < 10000; i++) test_copy (lhs, rhs); } Code $ g++ t.cc -O3 $ time ./a.out real 0m2.617s user 0m2.549s sys 0m0.002s $ g++ t.cc -O3 -fno-inline $ time ./a.out real 1m21.080s user 1m19.243s sys 0m0.009s Второй запуск с опцией -fno-inlline (который запрещает компилятору делать инлайн) соответствует "академической" реализации классов, в которых интерфейс строго отделён от реализации (т.е. в хидер выносятся только описания, а все реализации остаются в файле *.cpp). Грамотная реализация (в которой учтено, что компилятор работает с инлайном), как мы видим, отработала быстрее более, чем на порядок. Понятно, что пример искусственный, но он демонстрирует ту концепцию, в рамках которой разрабатывался язык Си++ со своим библиотечным окружением
0
|
||
|
Ушел с форума
|
|||
| 20.08.2013, 11:36 | |||
Имелось в виду, что для современных компиляторов одинаково легко встроить как функцию, определение которой "под рукой", так и функцию, определение которой находится в другой единице трансляции/компоновки. То есть, возвращаясь к вопросу о "нанокомпиляторах". Выполнил Ваш тест три раза (VC++2008, x64, Core i5-2500). Единственное отличие от оригинального кода: test_copy сделана нешаблонной. 1) main и test_copy размещены в одной единице трансляции. Результат: 3 минуты 57 секунд. 2) main и test_copy размещены в разных единицах трансляции. Результат: 3 минуты 54 секунды. 3) main и test_copy размещены в разных единицах трансляции + использована опция LTCG. Результат: 3 минуты 40 секунд.
0
|
|||
|
|
|||
| 20.08.2013, 12:04 | |||
|
Добавлено через 19 минут Попробовал режим -flto на gcc. Предположение по косвенным признакам подтверждается. Попробовал на нашем проекте (порядка 1500 исходников, объём исходников порядка 100 мегабайт). Время компиляции замедлилось несущественно (что-то типа 10%). Производительность не изменилась никак. Возможно, были какие-то ускорения в размерах флуктуаций измерений, но реального увеличения производительности не наблюл.
0
|
|||
|
Ушел с форума
|
|||
| 20.08.2013, 12:56 | |||
|
Компилятор счел, что для этого нет оснований. Тем не менее, определенная оптимизация все равно была выполнена. Кстати, на 32-битной машине я с помощью LTCG на этом же тесте получил еще больший прирост - порядка 25%. приводит к генерации более быстрого кода, чем реализация в исходных файлах. И это хитро, потому что STL, как и надлежит шаблонным классам, реализована в заголовках, и подтвердить или опровергнуть обратное, используя код STL, не представляется возможным. Думаю, единственная возможность расставить все точки над "i" - это найти какую-нибудь библиотеку, которая может собираться как в варианте header-only, так и как набор h+cpp. Возможно, в Boost что-то такое найдется. И вот по результатам ее запуска уже делать выводы.
0
|
|||
|
|
||||
| 20.08.2013, 13:08 | ||||
|
- в этом режиме более агрессивно работает инлайн (или какие-то дополнительные оптимизации) - библиотеки stl поставляются с сохранённым промежуточным представлением. Других вариантов, почему межмодульные оптимизации имеют эффект на исходнике из одного модуля, я не вижу. Естественно, эксперимент на на 100% "чистый", т.к. при реализации в библиотеке могли бы быть использованы другие оптимизации, при реализации в библиотеке была бы совсем другая раскладка по взаимному положению функций (и, соответственно, нагрузке на кэш), но вся это разница - доли процента или проценты. На фоне того, как у нас разница в производительности была в разы
0
|
||||
|
Ушел с форума
|
|||
| 20.08.2013, 13:37 | |||
|
Думаю, объяснить эффект LTCG можно, если думать про него не как про IPO, а именно как про вторую фазу оптимизации. Которая в обычном режиме не выполняется. Эффект от -fno-inline более глубокий, чем ты описываешь - он отключает инлайнинг по всему коду. Если у меня есть функции A и B, размещенные в разных единицах трансляции, то даже без IPO я могу рассчитывать хотя бы на то, что компилятор встроит код STL в тела A и B. При использовании -fno-inline и этого встраивания не будет.
0
|
|||
|
|
||||||||||||
| 20.08.2013, 14:06 | ||||||||||||
|
========== Реализация методов в хидере ========== C++ // Файл t1.cc #include "t.h" #define SIZE 10000 #define COUNT 100000 /* Атрибут втыкаем для того, чтобы отрезаться от цикловых оптимизаций * вточке вызова и замерить условно чистое время работы данной функции */ void __attribute__((noinline)) test_func (void) { Array array (SIZE); for (int i = 0; i < SIZE; i++) { Elem elem (i); array.Set (i, elem); } for (int i = 0; i < SIZE; i++) { Elem elem = array.Get (i); elem.Set (elem.Get() + 1); array.Set (i, elem); } } int main (void) { for (int i = 0; i < COUNT; i++) test_func (); return 0; } C++ // Файл t.h class Elem { private: int x; public: Elem () { x = 0; } Elem (int _x) { x = _x; } int Get (void) { return x; } void Set (int _x) { x = _x; } }; class Array { private: Elem *elems; public: Array (unsigned size) { elems = new Elem[size]; } ~Array () { delete elems; } Elem Get (unsigned index) { return elems[index]; } void Set (unsigned index, const Elem &elem) { elems[index] = elem; } };
Файл t1.cc остаётся без изменений. Из файла t.h удаляем все реализации C++ // Файл t.h class Elem { private: int x; public: Elem (); Elem (int _x); int Get (void); void Set (int _x); }; class Array { private: Elem *elems; public: Array (unsigned size); ~Array (); Elem Get (unsigned index); void Set (unsigned index, const Elem &elem); }; C++ // Файл t2.cc #include "t.h" Elem::Elem () { x = 0; } Elem::Elem (int _x) { x = _x; } int Elem::Get (void) { return x; } void Elem::Set (int _x) { x = _x; } Array::Array (unsigned size) { elems = new Elem[size]; } Array::~Array () { delete elems; } Elem Array::Get (unsigned index) { return elems[index]; } void Array::Set (unsigned index, const Elem &elem) { elems[index] = elem; }
1
|
||||||||||||
|
Ушел с форума
|
|
| 20.08.2013, 14:55 | |
|
+1, спасибо за реальный тест.
Запустил его на своей рабочей машине, код не трогал, только поменял декларацию "__attribute__((noinline))" на "__declspec(noinline)" (в VC++ это одно и то же). Также, для более рельефных результатов, я увеличил оба значения SIZE и COUNT в пять раз. Итак, результаты (x86, Visual C++ 2008, Core i5-2500). 1) Реализация методов в хидере. Время: 1 минута 3 секунды. 2) Реализация методов в отдельном файле. И здесь нас ждал вполне предсказуемый фейл. Время: 4 минуты 9 секунд. 3) Реализация методов в отдельном файле + опция LTCG. Время: 25 секунд. Кстати, в точности такой же результат получается, если использовать LTCG для реализации методов в хидере. Подтверждая, что компилятору без разницы, где находится определение - в заголовке или в файле реализации.
0
|
|
| 20.08.2013, 14:55 | |
|
Помогаю со студенческими работами здесь
60
Глобальные указатели. Плохо или хорошо? молодняк получил пр=0 хорошо или плохо?
Статические функции-члены - хорошо или плохо? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут
Суть:
- Группа наркоманов из 10 человек.
- Только один инфицирован ВИЧ.
- Колются одной иглой.
- Колются раз в день.
- Колются последовательно через. . .
|
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
|
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
|
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . .
а удачный момент так и не приходит.
|
|
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица.
Задача: зафиксировать три левых колонки в отчете.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
/ / . . .
|
Настройки VS Code
Loafer 13.04.2026
{
"cmake. configureOnOpen": false,
"diffEditor. ignoreTrimWhitespace": true,
"editor. guides. bracketPairs": "active",
"extensions. ignoreRecommendations": true,
. . .
|
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2.
Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива.
Было так:. . .
|
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2.
Задача: реализовать контроль корректности заполнения дат назначения. . .
|