Название: std::shared_ptr и множественное наследование Отправлено: RedDog от Апрель 24, 2015, 11:28 Как правильно создать shared_ptr если класс унаследован от нескольких родителей:
Код: class CPingAdmin : public QObject, xmlrpc_c::method Пытаюсь создать shared_ptr: Код: std::shared_ptr< xmlrpc_c::methodPtr > PingAdmFunc /usr/include/c++/4.7/ext/new_allocator.h:110: ошибка: 'xmlrpc_c::method' is an inaccessible base of 'CPingAdmin' Название: Re: std::shared_ptr и множественное наследование Отправлено: Пантер от Апрель 24, 2015, 11:41 Наследуешься от xmlrpc_c::method, а тип пойнтера xmlrpc_c::methodPtr.
Название: Re: std::shared_ptr и множественное наследование Отправлено: RedDog от Апрель 24, 2015, 11:45 Если я делаю вот так:
Код: class CPingAdmin : public xmlrpc_c::method Но мне нужен в данном случае Qt-шный сигнал из класса, поэтому пришлось добавить QObject. Название: Re: std::shared_ptr и множественное наследование Отправлено: Пантер от Апрель 24, 2015, 12:05 class CPingAdmin : public QObject, public xmlrpc_c::method
Название: Re: std::shared_ptr и множественное наследование Отправлено: RedDog от Апрель 24, 2015, 13:07 class CPingAdmin : public QObject, public xmlrpc_c::method Спасибо, помогло.Но появилась новая проблема - коннект сигнала к слоту: Код: std::shared_ptr< xmlrpc_c::methodPtr > PingAdmFunc Цитировать QtCore/qobject.h:215: ошибка: no type named 'Object' in 'struct QtPrivate::FunctionPointer<const char*>' Название: Re: std::shared_ptr и множественное наследование Отправлено: Igors от Апрель 24, 2015, 14:00 Но появилась новая проблема - коннект сигнала к слоту: Нужно кросс-привестисьЦитировать QtCore/qobject.h:215: ошибка: no type named 'Object' in 'struct QtPrivate::FunctionPointer<const char*>' Код
[OFF] Написано мало, но вот понять уже не так просто - заслуга "xmlrpc_c::methodPtr". И "крутые" скобки с пробелами этого не компенсируют :) [/OFF] Название: Re: std::shared_ptr и множественное наследование Отправлено: Nimbus от Апрель 24, 2015, 14:32 Если я делаю вот так: Код: class CPingAdmin : public xmlrpc_c::method Но мне нужен в данном случае Qt-шный сигнал из класса, поэтому пришлось добавить QObject. std::make_shared вызывает placement new, и затем конструктор и переданными ему аргументами. Зачем вы два раза создаёте объект xmlrpc_c::method? Правильно так: Код: std::shared_ptr< xmlrpc_c::method > PingAdmFunc = std::make_shared< CPingAdmin >(); Код: std::shared_ptr< CPingAdmin > PingAdmFunc = std::make_shared< CPingAdmin >(); std::make_shared и служит для того, чтобы самому не вызывать оператор new, а заодно и расположить объект и его счётчик ссылок в одном куске памяти + ещё какие-то там оптимизации. Заодно советую почитать про enable_shared_from_this. Название: Re: std::shared_ptr и множественное наследование Отправлено: RedDog от Апрель 24, 2015, 15:01 std::make_shared вызывает placement new, и затем конструктор и переданными ему аргументами. Так не работает, если внимательно посмотреть сто создается в шареде xmlrpc_c::methodPtr а не xmlrpc_c::methodЗачем вы два раза создаёте объект xmlrpc_c::method? Правильно так: Код: std::shared_ptr< xmlrpc_c::method > PingAdmFunc = std::make_shared< CPingAdmin >(); Код: std::shared_ptr< CPingAdmin > PingAdmFunc = std::make_shared< CPingAdmin >(); std::make_shared и служит для того, чтобы самому не вызывать оператор new, а заодно и расположить объект и его счётчик ссылок в одном куске памяти + ещё какие-то там оптимизации. Заодно советую почитать про enable_shared_from_this. Название: Re: std::shared_ptr и множественное наследование Отправлено: Nimbus от Апрель 24, 2015, 16:02 Так не работает, если внимательно посмотреть сто создается в шареде xmlrpc_c::methodPtr а не xmlrpc_c::method Окей, тогда из текста ошибки ('xmlrpc_c::method' is an inaccessible base of 'CPingAdmin'), понятно, что вы наследуетесь приватно от xmlrpc_c::method. Отсюда и проблема.то есть нужно так Код: class CPingAdmin : public QObject, public xmlrpc_c::method Название: Re: std::shared_ptr и множественное наследование Отправлено: Igors от Апрель 24, 2015, 16:24 Код: std::shared_ptr< xmlrpc_c::methodPtr > PingAdmFunc Но мне нужен в данном случае Qt-шный сигнал из класса, поэтому пришлось добавить QObject. std::make_shared вызывает placement new, и затем конструктор и переданными ему аргументами. Зачем вы два раза создаёте объект xmlrpc_c::method? Правильно так: Код: std::shared_ptr< xmlrpc_c::method > PingAdmFunc = std::make_shared< CPingAdmin >(); 1) Зачем здесь make_shared? Почему не просто Код: std::shared_ptr< xmlrpc_c::method > PingAdmFunc(new CPingAdmin); 2) А как же у ТС откомпилилось - ведь конструктора xmlrpc_c::method принимающего указатель наверняка нет. Что же произошло? Спасибо Название: Re: std::shared_ptr и множественное наследование Отправлено: Nimbus от Апрель 24, 2015, 16:38 1) Зачем здесь make_shared? Почему не просто Код: std::shared_ptr< xmlrpc_c::method > PingAdmFunc(new CPingAdmin); 2) А как же у ТС откомпилилось - ведь конструктора xmlrpc_c::method принимающего указатель наверняка нет. Что же произошло? Видимо, я наивно предположил, что xmlrpc_c::methodPtr -- это typedef method * methodPtr внутри класса xmlrpc_c::method.Как оказалось, это отдельный класс, как раз принимающий в конструктор указатель на xmlrpc_c::method, что автор и продемонстрировал. Приватное наследование от этого класса как раз и привело к такой ошибке. Спасибо Не за что ;-)Название: Re: std::shared_ptr и множественное наследование Отправлено: Igors от Апрель 25, 2015, 12:04 Ну легко же нагугливается (http://stackoverflow.com/a/20895705/2080453). Мдааа... Аргументация впечатляетЦитировать The difference is that std::make_shared performs one heap-allocation, whereas calling the std::shared_ptr constructor performs two. Как говорится "вспомнила баба как девкой была". Как c QString - так никто число malloc не считает (хоть их там тьма), а тут во как - аж 2(!) вместо одного, ай-яй-яй. Дальше еще интереснееЦитировать Since there there's only one allocation, the pointee's memory cannot be deallocated until the control block is no longer in use. A weak_ptr can keep the control block alive indefinitely. В общем я так понял что weak_ptr не обещает корректности если шареный указатель создан через make_shared. Не слабо!В общем еще раз убедился что изучать std надо в меру. Название: Re: std::shared_ptr и множественное наследование Отправлено: _Bers от Апрель 25, 2015, 12:56 Цитировать Since there there's only one allocation, the pointee's memory cannot be deallocated until the control block is no longer in use. A weak_ptr can keep the control block alive indefinitely. В общем я так понял что weak_ptr не обещает корректности если шареный указатель создан через make_shared. Не слабо!поведение weak_ptr вполне себе корректно. под капотом есть два счетчика: количество сильных ссылок и слабых. кроме этого - указатель на сам объект-ресурс смарт-поинтера. 1. случай с двумя аллокациями: Код: shared_ptr<resource> sm (new resource); имеем два указателя: на счетчики, и на объект-ресурс. когда количество сильных ссылок станет равным нулю, будет запущен деструктор объекта-ресурса. затем, будет освобождена память под объект-ресурс. память под счетчики будет освобождена только и только тогда, когда количество и сильных, и слабых ссылок будет равным нулю. таким образом, последний шаред_птр грохнет объект-ресурс, и освободит его память. последний смарт-поинтер (шаред или вик) грохнет объект-счетчиков, и освободит его память. в случае, если в памяти где то будет оставаться живой шаред_птр, то в памяти будет висеть и объект-ресурс, и объект-счетчиков. в случае, если в памяти где то будет оставаться живой вик_птр, то в памяти будет висеть объект-счетчиков. недостатки: две аллокации - две дорогостоящие операции выделея, и две ещё более дорогостоящих операций по освобождению. при этом, объект-ресурс и объект-счетчик разбрасываются по самым разным адресам, что провоцирует кэш-миссы. (при доступе к ним, придется постоянно подгружать то одну, то другую страницы памяти). 2. случай с одной аллокацией: Код: shared_ptr<resource> sm = std::make_shared<resource>(); make_shared разом выделяет большой кусок, в котором располагает и объект-счетчиков, и объект-ресурс. например, так: Цитировать [ [счетчик сильных ссылок][счетчик слабых ссылок][ [ресурс ] ] sizeof(uint32_t) sizeof(uint32_t) sizeof(resource) зная размеры всех задействованных типов (размеры счетчиков, и размер ресурса), и принцип упаковки, можно легко получать доступ к счетчикам, или к объекту-ресурсу, расположенному в едином блоке памяти. данный способ более эффективный, по сравнению с первым случаем: меньше дорогостоящих операций выделения памяти, объекты аллоцируются рядышком, в непрерывном блоке памяти, а не разбрасываются по всей памяти, что является кэш-френдли. аналогично первому случаю, последний шаред_птр грохнет объект-ресурс (позовет деструктор) но пока счетчик слабых ссылок ещё не обнулился, нельзя удалять саму память. иначе, вик_птр станут неконсистентными. таким образом: пока есть хотя бы один живой шаред_птр, то ресурс будет живой. если нет ни одного шаред_птр, то ресурс будет уничтожен, но сама память будет висеть до тех пор, пока ещё остается хотя бы один вик_птр. резюмируя: в 1 случае память частями выделяется, и частями освобождается. во 2 случая память выделяется целиком за раз, и так же за раз целиком освобождается. на мой взгляд, 2й способ работы со смарт-поинтерами предпочтительнее, нежели первый. зная немножко, как оно там устроенно внутри, я понимаю, что 2й способ работает эффективнее. но если пренебречь этой эффективностью, то с точки зрения использования особой разницы нет. Название: Re: std::shared_ptr и множественное наследование Отправлено: Old от Апрель 25, 2015, 13:16 но если пренебречь этой эффективностью, Я бы еще добавил про исключения... но не буду. :)то с точки зрения использования особой разницы нет. Потому что, главная фраза темы уже сказана: В общем еще раз убедился что изучать std надо в меру. Все уточняющие вопросы в теме, задавались исключительно, что-бы сказать это. :) Тему можно закрывать. ;D Название: Re: std::shared_ptr и множественное наследование Отправлено: Igors от Апрель 25, 2015, 14:52 если нет ни одного шаред_птр, то ресурс будет уничтожен, Понял, в случае make_shared зовется деструктор - а не deleteдве аллокации - две дорогостоящие операции выделея, Ну дорого/дешево познается в сравнении. Напр сколько здесь будет таких операций?и две ещё более дорогостоящих операций по освобождению. Код :) А что-то типа QRegExp еще похлеще. Но ни разу не видел чтобы это хоть кого-то остановило, Напротив, задействовать QRegExp считается делом чести. Как-то слышал типа Цитировать А вы знаете - ведь скриптовые языки по скорости уже догоняют плюсы! Наверное уже и обогнали :)Название: Re: std::shared_ptr и множественное наследование Отправлено: navrocky от Апрель 28, 2015, 11:26 Ну мне пригодился make_shared, и даже не он а allocate_shared, когда я уперся в фрагментацию памяти. Выделялось несколько миллионов объектов по 100 байт. Пришлось городить пул и выделять через allocate_shared.
|