2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
|||||||||||
1 | |||||||||||
Нужно разобрать смысл строки в variadic Tempalates15.12.2015, 21:23. Показов 1392. Ответов 9
Метки нет (Все метки)
Добрый вечер,
хочу понять строки 9-13. С примера вижу, что for_each_argument не вызывает себя рекурсивно, что уже странно для меня - так я думал, что в этом её и смысл судя по моим наработкам в этой области, вот: Рекурсивный вызов аргументов
Вопросы: 1) как я понял t это тип int[cout_of_args] - тоесть int[3] для нашего примера 2) зачем там int захардкожен ? 3) как я понял t{} это анонимный массив 4) ... заставит заполнить этот массив 3 раза 5) зачем там 0 и темболе после запятой 6) зачем явное СИ-стайл приведение этого массива к (void)
0
|
15.12.2015, 21:23 | |
Ответы с готовыми решениями:
9
Variadic Templates - как обращаться к аргументам variadic-функции? разобрать смысл строк Variadic templates, или variadic constructor в шаблоне, или прочие извращения Нужно разобрать код |
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
|
|
15.12.2015, 22:09 | 2 |
Сообщение было отмечено rikimaru2013 как решение
Решение
1) Да.
2) Потому что не используется, используется побочный эффект при заполнении массива нулями. 3) Да. 4) Нет, в массив сразу заливается 3 выражения вида Код
f(argN), 0 5) Чтобы заполнить массив. Что вернёт f - неизвестно, а если через запятую поставить нолик, то всё выражение и станет ноликом, который смело можно заливать в массив. 6) Чтобы избежать предупреждения о неиспользуемом значении. В итоге оптимизатор просто выкинет ненужную суету вокруг неиспользуемого массива и заполнения ноликами, оставит только 3 вызова функции f с приведёнными аргументами. Добавлено через 3 минуты Вся эта суета нужна только для того, чтобы использовать оператор распаковки на аргументах, вызвав функцию f последовательно для каждого из них. Просто так это сделать синтаксис не даёт, приходится использовать контекст заполнения массива.
1
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
||||||
15.12.2015, 23:22 [ТС] | 3 | |||||
Nick Alte,
получается: 1) если бы мы не выдумали бы этот анонимный массив, у нас бы не получилось вызвать 3 раза подряд заполнение? Смущает, что играем вокруг массива и значения нуля. Это какое-то особеность? 2) получается мы б могли аккамулировать return value
0
|
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|||||||||||||||||||||||||||||||
16.12.2015, 00:15 | 4 | ||||||||||||||||||||||||||||||
Сообщение было отмечено rikimaru2013 как решение
Решение
ага
трюк с массивом используется, что бы избавиться от рекурсии. массив получается фиктивным. ну то есть, он не используется. значения массива нигде не используются. это все равно, что не использованная переменная. компилятор пофиксит и выбросит его из компиляции. зато никаких рекурсий. кстати:
мы, программисты, в курсе, что у нас тут неиспользуемая переменная. что бы компилятор не доставал предупреждениями. можно убрать войд и глянуть: если будет предупреждение, значит в релизе он эту переменную 100% соптимизирует. а вот насчет того, сможет ли он соптимизировать рекурсию - вот здесь у меня больше "смущений". ага Добавлено через 6 минут
открытые фигурные скобки - инициализация то есть, мы хотим инициализировать объект t (в данном случае это - массив) значением:
результатом всего выражения будет expr2 таким образом: заполнить массив t данными:
но результатом всего выражения будет ноль идущий после запятой таким образом массив будет заполнен нулями, и при этом будет выполнены запуски функции для всего вариадик пакета потом компилятор пофиксит, что массив не используемый, и оптимизирует его. останутся только запуски функции (хотя по хорошему лучше все таки глянуть ассм, что бы убедиться что он реально оптимизует)
1
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
|||||||||||
16.12.2015, 00:39 [ТС] | 5 | ||||||||||
сложно понять закономерность распоковки
для аргумента метода
Стоит ли такие махинации с инициализацией анонимного массива распаковаными аргументами? Как я понял с плюсов, что стек под вызов функции(память под его параметры) выделяются 1 раз, а не рекурсивно (пока не распакован последний существует первый стек вызова). С минисов,
0
|
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|
16.12.2015, 01:03 | 6 |
рассмотрим худший вариант:
без оптимизаций, количество разнотипных аргументов велико, тогда: 1. рекурсия. компилятору придется инстанцировать уйму перегрузок под весь зоопарк типов что плохо для времени компиляции, и для размера бинарника. а при рекурсивном вызове, вся эта толпа аргументов будет каждый раз копироваться, передаваясь от одной перегрузке к другой. при этом будет израсходовано стековой памяти в несколько раз больше, чем изначальный размер вариадик пакета аргументов. потому что на каждой итерации рекурсии будет заново расходоваться стековая память под все переданные аргументы. 2. фиктивный массив несмотря на то, что он не используется, под него придется выделить память. то бишь зазря израсходуется стековая память в размере sizeof(char)*количество-аргументов-в-пакете но в итоге израсходуется намного меньше стека, чем в случае с рекурсией. при каждом вызове функции, массив будет заново инициализироваться нулями, то есть зазря тратим машинное время на ненужную инициализацию. но при этом вызов целевой функции все равно будет происходить быстрее, чем в случае с рекурсией. потому что в случае с рекурсией на обработку одного аргумента приходится копировать весь остаточный вариадик пакет. а в случае с массивом - только вписать один нолик. -------------------------------------------------------------------------------------- на практике вряд ли там будет много аргументов, и скорее всего компилятор в обоих случаях выполнит оптимизации, так что не удивлюсь если ассмо-выхлоп в обоих случаях будет плюс/минус одинаковый. в общем, имхо нет смысла заморачиваться. лично мне нравится способ с фиктивным массивом просто потому, что тупо меньше кода писать приходится.
0
|
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
|
|
16.12.2015, 01:36 | 7 |
rikimaru2013, код не идеален на 100%. По-хорошему надо добавить еще одно приведение к void: static_cast<void>(f(forward<Args>(args)).
Не всегда
0
|
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
|
|
24.12.2015, 12:37 | 8 |
rikimaru2013, hoggy, так вы уловили случай, что если я передам функцию f, которая будет возвращать объект типа, у которого перегружен оператор запятая, то оно в лучшем случае не скомпилируется (если оператор будет возвращать не число), а в худшем послужит источником сложно уловимых багов (в случае каких-то side effect'ов)?
Поэтому нужно отбрасывать значение, возвращаемое f, - это делается через ее каст к void.
1
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
|
24.12.2015, 13:12 [ТС] | 9 |
ct0r, уловили же ж. ) А вот вы некрофил - но в хорошом смысле. Хотя какой тут хороший смысл ))
0
|
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|
24.12.2015, 19:39 | 10 |
0
|
24.12.2015, 19:39 | |
24.12.2015, 19:39 | |
Помогаю со студенческими работами здесь
10
Нужно разобрать тему Нужно разобрать задачу Нужно разобрать мишь Нужно разобрать код? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |