|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
|
Опции темы | Поиск в этой теме |
25.08.2014, 12:12 | #1 |
Форумчанин
Регистрация: 14.12.2012
Сообщений: 668
|
Объект способный хранить указатель на фукцию и на данные
Здравствуйте.
Из-за того, что меня не совсем устраивает std::function, решил написать собственную замену. Вышло примерно следующее: Код:
Size_check демонстрирует равенство указателей двух типов. Но программа падает при работе с указателями на функцию. В онлайн компиляторах, программа падает и при использовании массива int'ов. Вопросы: 1. Чем отличаются указатель на функцию от указателя на данные? 2. Каким должен быть объект, способный хранить оба типа указателя (не одновременно)? |
25.08.2014, 12:32 | #2 |
Старожил
Регистрация: 16.12.2011
Сообщений: 2,329
|
|
25.08.2014, 12:39 | #3 | |
Форумчанин
Регистрация: 14.12.2012
Сообщений: 668
|
Цитата:
В целом до меня дошло. Здесь: Wrapper(_Fn &fn) : fn(&fn) {}, когда передается обычная функция, берется указатель на указатель. Нужно написать прокладку для взятия адреса. |
|
25.08.2014, 12:55 | #4 | |
Старожил
Регистрация: 16.12.2011
Сообщений: 2,329
|
Цитата:
std::function - это обертка над функторами, которые в свою очередь используют статическую связку между собой и вызываемой функцией. Другими словами, эти функторы не хранят внутри себя указатель-на-функцию. А вместо этого фиксируют вызываемую функцию через параметр шаблона. Связка через указатель на функцию - это динамическое связывание, которое не гарантирует 100% inline, использует передачу данных через аргументы функций, и отягощает sizeof функтора. Пример фиксации вызываемой функции через параметр шаблона: http://rextester.com/KYRE18162 Код:
|
|
25.08.2014, 13:04 | #5 |
Форумчанин
Регистрация: 14.12.2012
Сообщений: 668
|
Кто вам сказал, что std::function внутри себя ничего не хранит? Хранит, более того, выделяет помять под этот указатель через new, в куче. О производительности после этого ... . Моя реализация делает ссылки, размер которых известен, благодаря этому можно избавиться от выделения памяти в куче. Единственный ограничение - если function_ref инициализируется лямбдой, то лямбда должна существовать во время вызова. std реализация допускает такой вызов.
|
25.08.2014, 13:06 | #6 |
Форумчанин
Регистрация: 14.12.2012
Сообщений: 668
|
Кстати, проблемы не решил.
|
25.08.2014, 19:05 | #7 |
Форумчанин
Регистрация: 14.12.2012
Сообщений: 668
|
Я сам был виноват, не сразу осознал, что Wrapper_base имеет виртуальный метод, следовательно нужен доп. размер под таблицу вирт-ых функций. Получилось что-то такое:
Код:
Еще одна реализация (не моя) http://habrahabr.ru/post/159389/ Последний раз редактировалось 220Volt; 25.08.2014 в 22:14. Причина: Добавил alignas(Wrapper<void()>) |
25.08.2014, 19:22 | #8 |
Форумчанин
Регистрация: 14.12.2012
Сообщений: 668
|
В целом, я конечно велосипед написал. Здесь пишут,http://en.cppreference.com/w/cpp/uti...ction/function
что если оборачивать функции в std::reference_wrapper, то никаких выделений памяти из кучи не будет, всё внутри std::function. Но в std библиотеке моего компилятора нет std::function. Так что пришлось этим заниматься. |
26.08.2014, 21:41 | #9 |
Форумчанин
Регистрация: 14.12.2012
Сообщений: 668
|
Очередные грабли (компилятор ругается - нарушение strict aliasing, строчка с reinterpret_cast). http://habrahabr.ru/post/114117/.
Копаться во всех тонкостях нет времени. Можно ли положиться на такой код, с точки зрения попадание на грабли strict aliasing'a (на этот код предупреждений нет): Код:
|
26.08.2014, 22:08 | #10 |
Старожил
Регистрация: 16.12.2011
Сообщений: 2,329
|
Можно. Это хорошее решение.
Если: Код:
Код:
Тем не менее, не рекомендую вам использовать чаровый буфер хранения без никто. Поскольку в этом случае вас ожидает ситуация куда похуже, чем поломанный алиасинг: доступ к объекту по невыровненному адресу, что в общем случае является UB: на новых процессорах резко ухудшиться производительность. На старых процессорах может привести к поломке - крэш. http://rextester.com/AFSG72652 Код:
Если реинтерпретировать его, как объект класса, то доступ к этому объекту так же получится по не выровненному адресу. Самый простой способ разом решить и проблему алиасинга, и проблему неровных адресов - после чарового буфера добавить указатель. И работать с объектом через этот указатель: http://rextester.com/LVH79815 Код:
|
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Как лучше хранить игровые данные | CeHTuJI | Общие вопросы Delphi | 3 | 27.09.2013 15:15 |
Классы. Указатель на объект в классе. | Son | Помощь студентам | 2 | 21.05.2013 18:45 |
Как хранить иерархические данные в реляционной бд? | Хару Атари | Помощь студентам | 1 | 24.03.2013 17:46 |
Указатель на объект внутри класса | WildTaburet | Visual C++ | 1 | 01.10.2012 14:34 |
где хранить данные принято? | yuran111 | Общие вопросы Delphi | 36 | 12.05.2011 00:23 |