X>lambda.cpp: In function ‘int main()’:
X>lambda.cpp:4:19: error: use of deleted function ‘main()::__lambda0::<lambda>()’
X> decltype(lambda) lb;
X> ^
X>lambda.cpp:3:17: note: a lambda closure type has a deleted default constructor
X> auto lambda = [](){return 33;};
X> ^
J>>>и внезапно все накладные расходы исчезают...
SVZ>>Я не имею доступа к стандартной библиотеке С++'11, поэтому любопытства ради... SVZ>>указатель на deleter внутри std::unique_ptr хранится? Если да, то накладные расходы никуда не ушли, только читабельность кода просела. J>в unique_ptr хранится не указатель, а сам делетер. в часном случае (который привел k.o.) делетер — это указатель на функцию. Конечно в этом случае мы имеет 4 профуканных байта. J>Я обернул этот делетер в ламбду. По сути лямбда — это функтор, структура с перекрытым оператом (). так эта лямбда не захватывает переменных(у неё пустой список []) , то у структуры нету полей. А раз так, то и в unique_ptr нечему хранится, никакого оверхеда нет.
Вообще-то по Стандарту объект не может быть нулевого размера. Значит даже функтор будет занимать хотя бы один 1 байт, плюс выравнивание...
Так что тут что указатель на функцию, что функтор — разницы нет. Может оптимизатор что-то поправит, но я сомневаюсь.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, Jack128, Вы писали:
KO>>А я нигде не утверждал, что my_cool_custom_deleter это указатель на функцию.
J>а коду my_cool_custom_deleter_functor на это пофиг. Функция, функтор, без разницы, главное чтобы можно было вызвать my_cool_custom_deleter(x);
А коду, которому придется использовать my_cool_custom_deleter_functor может быть не пофиг.
J>>>Я обернул этот делетер в ламбду. По сути лямбда — это функтор, структура с перекрытым оператом (). так эта лямбда не захватывает переменных(у неё пустой список []) , то у структуры нету полей. А раз так, то и в unique_ptr нечему хранится, никакого оверхеда нет.
KO>>Только теперь, объект deleter'а, по-сути, гвоздями прибит к типу указателя.
J>и? Примера демонстрирующего проблему я так понимаю ты не напишешь?
SVZ>Вообще-то по Стандарту объект не может быть нулевого размера. Значит даже функтор будет занимать хотя бы один 1 байт, плюс выравнивание...
ну все не так просто. смотри упомянутый выше EBO.
SVZ>Так что тут что указатель на функцию, что функтор — разницы нет. Может оптимизатор что-то поправит, но я сомневаюсь.
А я нет, потому что проверил. И gcc, студия (2013ая) убирают этот байт.
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, Jack128, Вы писали:
J>>выделенное ни на какие мысли не наводит? X>я не спрашивал почему не компилится, я подтвердил что не компилится.
так ты же потребовал конструктор по умолчанию, а для deleter'а, такого требования, вроде бы, нет.
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Jack128, Вы писали:
KO>>>А я нигде не утверждал, что my_cool_custom_deleter это указатель на функцию.
J>>а коду my_cool_custom_deleter_functor на это пофиг. Функция, функтор, без разницы, главное чтобы можно было вызвать my_cool_custom_deleter(x);
KO>А коду, которому придется использовать my_cool_custom_deleter_functor может быть не пофиг.
Здравствуйте, Jack128, Вы писали:
J>Здравствуйте, k.o., Вы писали:
KO>>Здравствуйте, Jack128, Вы писали:
KO>>>>А я нигде не утверждал, что my_cool_custom_deleter это указатель на функцию.
J>>>а коду my_cool_custom_deleter_functor на это пофиг. Функция, функтор, без разницы, главное чтобы можно было вызвать my_cool_custom_deleter(x);
KO>>А коду, которому придется использовать my_cool_custom_deleter_functor может быть не пофиг.
J>а тут что не так?
ну так, тот же самый пример, объекты deleter'ов разные, а остальной код один и тот-же.
KO>все-таки, есть некоторая разница с хранением my_cool_custom_deleter в объектах unique_ptr?
если my_cool_custom_deleter это функция, адрес которой известен статически, она не будет храниться в unique_ptr.
если это указатель на функцию или объект — то не надо использовать unique_ptr, он для этого не предназначен
unique_ptr это аналог T*, или T[], или кортежей (T*, Deleter) или (T[], Deleter),
если ты его комбинируешь с вектором получается что-то вроде (T*, Deleter)[], это совсем не (T*[], Deleter) .
просто не надо использовать вещи для чего они не предназначены, и не будет оверхеда
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, k.o., Вы писали:
A>если my_cool_custom_deleter это функция, адрес которой известен статически, она не будет храниться в unique_ptr. A>если это указатель на функцию или объект — то не надо использовать unique_ptr, он для этого не предназначен
а обосновать?
A>unique_ptr это аналог T*, или T[], или кортежей (T*, Deleter) или (T[], Deleter), A>если ты его комбинируешь с вектором получается что-то вроде (T*, Deleter)[], это совсем не (T*[], Deleter) .
A>просто не надо использовать вещи для чего они не предназначены, и не будет оверхеда
Так в чем же проблема с использованием unique_ptr и объекта deleter'а? в оверхеде?
Здравствуйте, k.o., Вы писали:
KO>так ты же потребовал конструктор по умолчанию, а для deleter'а, такого требования, вроде бы, нет.
ничего я не требовал. мне вообще это не нужно.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, k.o., Вы писали:
KO>>так ты же потребовал конструктор по умолчанию, а для deleter'а, такого требования, вроде бы, нет. X>ничего я не требовал. мне вообще это не нужно.
SVZ>Вообще-то по Стандарту объект не может быть нулевого размера. Значит даже функтор будет занимать хотя бы один 1 байт, плюс выравнивание... SVZ>Так что тут что указатель на функцию, что функтор — разницы нет. Может оптимизатор что-то поправит, но я сомневаюсь.
Там помнится хитро используется наследование. В результате sizeof(unique_ptr<void>)==sizeof(void*)
J>>>и внезапно все накладные расходы исчезают...
KO>>ну, если, к ним не относить расходы на приведение этого кода, хотя бы, в компилируемое состояние, то ты, безусловно прав.
J>афигеть. точно с запятой забыл.
J>Надеюсь так устроит ???
Здравствуйте, night beast, Вы писали:
NB>предположим, что my_cool_custom_deleter -- мембер класса: NB>
NB>template< typename Deleter >
NB>struct foo {
NB> Deleter my_cool_custom_deleter;
NB> // как определить вектор мембером?
NB> void test ( ) {
NB> auto my_cool_custom_deleter_functor = ??;
NB> std::vector<std::unique_ptr<X, decltype(my_cool_custom_deleter_functor)>> c;
NB> }
NB>};
NB>
Передавай его напрямую, по значению. Если он stateless — то на размер не повлияет, если stateful — то естественно повлияет.
Но если у тебя stateful deleter — тебе его пришлось бы таскать вместе с указателем и без unique_ptr. То есть unique_ptr никакого нового оверхеда тут не добавляет.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
NB>>предположим, что my_cool_custom_deleter -- мембер класса:
NB>>template< typename Deleter >
NB>>struct foo {
NB>> Deleter my_cool_custom_deleter;
NB>> // как определить вектор мембером?
NB>> void test ( ) {
NB>> auto my_cool_custom_deleter_functor = ??;
NB>> std::vector<std::unique_ptr<X, decltype(my_cool_custom_deleter_functor)>> c;
NB>> }
NB>>};
EP>Передавай его напрямую, по значению. Если он stateless — то на размер не повлияет,
код какой?
EP>если stateful — то естественно повлияет. EP>Но если у тебя stateful deleter — тебе его пришлось бы таскать вместе с указателем и без unique_ptr. То есть unique_ptr никакого нового оверхеда тут не добавляет.
дык о том и речь. он stateful, но в пределах вектора/класса/группы объектов.
допустим, в класс передается аллокатор, а в делетере хранится указатель на него.
естественно, таскать его с каждым элементом вектора -- лишний оверхед.
Здравствуйте, Jack128, Вы писали:
J>Здравствуйте, skeptic, Вы писали:
S>>Да и любой смарт указатель это всё таки больше чем S>>просто обёртка, не понятно с чем ты тут не согласен? J>а какой оверхед несет unique_ptr ??
Разговор был не про уник в частности, а про смарт поинтеры в целом.
Разговор был в контексте — да, смарт поинтеры отжимают долю у raw, но полностью не отожмут никогда,
разве что C++ станет очередным C#, но это уже совсем другая история. Вот с чем тут можно спорить?
Если говорить про уник, то да, это замена raw указателям, но
1. те кто работает на низком уровне в массе своей всё равно будут сидеть на сырых указателях
2. далеко не у всех есть и в скором времени будет доступ к компиляторам реализующим последний стандарт
А ещё интересно, а чего это вы тут все в ветке за уник прицепились? Есть же другие замечательные — шаред например.
Как дети, чё не скажи — 100500 слов протеста и литр слюны...
Здравствуйте, skeptic, Вы писали:
S>1. те кто работает на низком уровне в массе своей всё равно будут сидеть на сырых указателях
Зачем? S>2. далеко не у всех есть и в скором времени будет доступ к компиляторам реализующим последний стандарт
А что, без него умные указатели не заработают?
Здравствуйте, night beast, Вы писали:
NB>>>предположим, что my_cool_custom_deleter -- мембер класса: NB>
NB>>>template< typename Deleter >
NB>>>struct foo {
NB>>> Deleter my_cool_custom_deleter;
NB>>> // как определить вектор мембером?
NB>
std::vector<std::unique_ptr<X, Deleter>> c;
EP>>если stateful — то естественно повлияет. EP>>Но если у тебя stateful deleter — тебе его пришлось бы таскать вместе с указателем и без unique_ptr. То есть unique_ptr никакого нового оверхеда тут не добавляет. NB>дык о том и речь. он stateful, но в пределах вектора/класса/группы объектов. NB>допустим, в класс передается аллокатор, а в делетере хранится указатель на него. NB>естественно, таскать его с каждым элементом вектора -- лишний оверхед.
Да, в этом случае будет overhead. Но это не wrapping penalty, а penalty за лишние и неиспользуемые возможности(например move отдельного элемента вектора наружу). Для таких случаев можно использовать что-то типа boost::ptr_vector.
Точно также std::vector<int> даёт мини-оврхед в случаях фиксированного размера известного снаружи — тут подошёл бы std::unique_ptr<int[]>.