LINUX.ORG.RU

Замыкания, С++ и память

 , ,


0

4

Да простит мне публика ламерский вопрос. Вот в С++ есть замыкания. Я немного почитал про них, но всё равно не уверен, что понял.

Вот например

Я правильно понял, что closure object может присваиваться только копированием? И что если мы хотим, чтобы гигантские захваченные данные не копировались, мы должны решать это сами, захватывая такие ссылки объекты, которые реализуют нужное нам поведение с т.з. времени жизни? Просто я давно отстал от мира С++ и мне аж страшно на это всё смотреть.

★★★★★

У тебя русская «с» в тэге чтоли стоит? А то у меня в уведомлениях не появилось.

По теме, я не понял, в чём вопрос. Ты можешь захватить в лямбду объект как по ссылке, так и по значению, а также по rvalue ссылке (начиная с C++14). Можешь вообще весь scope захватить (&, =) <------ это не смайлик.

DELIRIUM ☆☆☆☆☆ ()
Последнее исправление: DELIRIUM (всего исправлений: 1)
Ответ на: комментарий от DELIRIUM

Нет, с объектом вопросов нет, что можно по-разному захватить объект - это я понял. Вопрос в другом. Само замыкание - это тоже объект. Вопрос в том, как происходит жизнь самого замыкания.

den73 ★★★★★ ()
Ответ на: комментарий от den73

По дефолту лямбда копируется, но ты можешь явно её мувнуть через std::move, чего делать не стоит никогда, а то получишь канделябром по кумполу.

DELIRIUM ☆☆☆☆☆ ()

ТС унылый тролль, при чем тут слово яр?

anonymous ()

Просто я давно отстал от мира С++ и мне аж страшно на это всё смотреть.

Зачем его смотреть, если он стал ну совсем страшным, а до лиспа всё равно, как до Луны пешком? Он даже в дремучем энтерпрайзе стал вымещаться всяким Го, а всё остальное так и продолжают писать в стиле «Си с классами», ибо ещё ведь и отлаживать надо, и клиентские корки расковыривать.

mv ★★★★★ ()
Ответ на: комментарий от DELIRIUM

ты можешь явно её мувнуть через std::move, чего делать не стоит никогда, а то получишь канделябром по кумполу.

Почему?

vzzo ★★★ ()
Ответ на: комментарий от mv

Мне интересно, как реализованы лямбды в языке без сборки мусора. Мне казалось естественным указать, как создаётся лямбда - на стеке или в куче, и соответственно, если она создаётся в куче, обязать пользователя её потом удалять. Но я не вижу в плюсах такого указания, посему представляю себе, что она всегда создаётся на стеке, а для возврата копируется.

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от DELIRIUM

чоэтавдруг? Обычно лямбду вообще на месте рисуют, и она таки мувается со всеми объектами.

anonymous ()
Ответ на: комментарий от den73

как как. Лямбда это просто сахар для чего-то типа

class blablaa {
    result_type operator ( )(...) 
    {
        тут код.
    }
    Type1 param1;
    Type2 &ref_param2;
    .....
}

соответственно ведет себя так как повел бы себя объект подобного класса. С мувами, копирование и прочим.

anonymous ()
Ответ на: комментарий от den73

Мне интересно, как реализованы лямбды в языке без сборки мусора.

Лямбды в цепепе - это всего лишь синтаксический сахар (аля упрощенная запись, DSL - как угодно) над функторами - т.е. классами с перегруженным оператором вызова функции - operator() :-) Память под объекты лямбд выделяется на стеке :-) Объекты лямбд имеют семантику значений - т.е. копируются/перемещаются :-)

#include <iostream>

struct Functor {
  int operator()(int value) { return value; }
};

int
main()
{
  auto lambda1 = [&](auto value) { return value; };
  auto lambda1_copy = lambda1;

  Functor lambda2;
  auto lambda2_copy = lambda2;

  std::cout << lambda1_copy(1) << std::endl;
  std::cout << lambda2_copy(2) << std::endl;
}

А ты что, на цепепе решил свой Яр писать? :-)

anonymous ()
Ответ на: комментарий от mv

Зачем его смотреть, если он стал ну совсем страшным

цепепе становится всё краше и краше :-) Не знаю, радоваться ли, грустить, но дела у цепепе, в плане использования его в проектах, идут в гору - 3-е место на TIOBE :-) В отличии от :-)

а до лиспа всё равно, как до Луны пешком?

На Лиспе нельзя делать то, что можно делать на цепепе :-) Приведи хотя бы один практический пример обратного :-)

а всё остальное так и продолжают писать в стиле «Си с классами»

Что всё? :-) Все новые проекты уже давно пишутся как минимум на цепепе-11 :-)

ибо ещё ведь и отлаживать надо, и клиентские корки расковыривать.

А Лиспе не надо? :-) Или там с отладкой всё хорошо? :-)

anonymous ()
Ответ на: комментарий от anonymous

На Лиспе нельзя делать то, что можно делать на цепепе

Например, нельзя отлаживать шаблоны. От слова «совсем». Зато найсово тащат в язык кучу всякого говна, чтоб молодежно было.

C++ мертв. Стандарты после C++11 просто пытаются (весьма безуспешно) насиловать труп. Вменяемый человек в это болото просто не пойдет, ибо под каждой строчкой уже переборно много сайдэффектов. А хипстер на C++ - это хипстер на C++, ничего толкового не напишет, как бы ни старался.

anonymous ()
Ответ на: комментарий от anonymous

Например, нельзя отлаживать шаблоны. От слова «совсем».

Ага, зато можно отлаживать макросы :-) Такие, как в каком-нибудь ASDF, где что-бы понять как работает какая-то его часть можно вывихнуть мозг, пока скомпилируешь макры г-на Фаре в уме :-)

C++ мертв.

Я так понимаю, мы о цепепе и Лиспе :-) Тогда если цепепе мёртв, то Лиспа даже не существует и никогда не существовало :-)

Стандарты после C++11 просто пытаются (весьма безуспешно) насиловать труп.

Ну а в Лиспе даже этого делать не пытаются, потому что Лиспа не существует, видимо :-) Кулхацкеры Лиспа уныло вторят про какие-то библиотеки, которые гораздо нужнее обновления стандарта, дают читать какие-то дополнения к стандарту и т.д. :-)

А хипстер на C++ - это хипстер на C++, ничего толкового не напишет, как бы ни старался.

Смотря что понимать под «толковым» :-) Что толкового написали на Лиспе? :-)

anonymous ()
Ответ на: комментарий от den73

Видимо ты идиот. Обьясни народу, причем тут слово яр касательно твоей тематики? Или ты свой говнотулкит так рекламируешь?

anonymous ()
Ответ на: комментарий от anonymous

Да, я протупил под вечер: просто ТС скинул линк на тред про std::function<>, я что-то и задумался про конструирование std::function<> из лямбды.

DELIRIUM ☆☆☆☆☆ ()
Ответ на: комментарий от anonymous

На Лиспе нельзя делать то, что можно делать на цепепе :-) Приведи хотя бы один практический пример обратного :-)

Ты и сам, наверное, догадываешься, что можно сделать в Лиспе, раз г-на Фарэ знаешь (он, кстати, в черепной коробке носит мозг необъятных размеров). Для меня самым ценным была возможность круто развернуть дизайн кода и постепенно вернуть функциональность окружающих блоков. В стартапном окружении, когда требования каждое утро новые, на плюсах было адово писать. Возможность прогнать тесты через полунерабочий прототип с новой архитектурой, не тратя время на борьбу с компилятором, убедившись в жизнеспособности такого подхода - самое ценное. Т.е. короткий time to market, пиэмы от счастья плачут.

Что всё? :-) Все новые проекты уже давно пишутся как минимум на цепепе-11 :-)

Да я вас умоляю, новые обои старый бордель не спасут. Пару новых финтифлюшек плюсовики используют, остальное - Си с классами. Но отлаживать их потёки и коррапты приходят сишники, почему-то.

А Лиспе не надо? :-) Или там с отладкой всё хорошо? :-)

Ой, отлично всё просто. У меня даже пример из реальной жизни заготовлен: в одном большом французском банке до сих пор крутится лисповая система, за поддержку которой банк чек на десятку в месяц выписывает. Когда в коде случается неприятность, она шлёт автору письмо с энвайронментом, он чинит баг, шлёт обратно емейлом патченный код, который применяется в живом образе и система продолжает с ближайшего рестарта.

mv ★★★★★ ()
Ответ на: комментарий от mv

Лиспер красавчик, всё как положено — вендор лок-ин, бас-фактор единица, баги на десятилетия вперёд. Только причём тут лисп?

fluorite ★★★★★ ()
Ответ на: комментарий от fluorite

Лиспер красавчик, всё как положено — вендор лок-ин, бас-фактор единица, баги на десятилетия вперёд. Только причём тут лисп?

Да бросьте, лисперов в сообществе было больше, чем нам в контору надо было. Причём, занятные персонажи. Один, например, защитил кандидатскую по философии (которая прям философия, а не философи доктор) и писал в Вестингаузе лисповый софт для загрузки реактора топливом.

Баг у меня в продакшене был один: вручную обрезал время до 32 бит и оно кончалось. Остальных клише, приписываемых к языкам с динамической типизацией, не было. Если релиз прошёл все тесты, у клиента никогда не глючил (за исключением обрезания времени). Тот же Xilinx HLS, написанный на плюсах, багов содержал в первых релизах несоизмеримо больше, чем наш лиспокомпилятор.

Хороший программист пишет хороший код, плохой - плохой. ЯП не важен.

mv ★★★★★ ()
Ответ на: комментарий от mv

ЯП важен. Хороший ЯП позволяет сконцентрироваться на решении задачи вместо чрезмерного отвлечения на детали реализации. Поэтому я не пишу на ассемблере, например :)

anonymous ()

Тогда нет повода не прорекламировать Rust здесь. Там это решается через ключевое слово move, которое перенесет кусок памяти во внутрь замыкания без какого-либо копирования. Поэтому Rust и няшка.

В Си++ есть похожая штука std::move, но как отписался один товарищ выше, в Си++ это будет очень рискованно, а вот в Rust компилятор защитит от повторного или неправильного использования (см. FnOnce и FnBox)

dave ★★★★★ ()
Ответ на: комментарий от den73

В Си++ замыкания и std::function - разные вещи. Как я понял (а могу ошибаться), замыкания создаются на стеке. А вот при боксинге превращаются в std::function, для которых обычно действует жесткое ограничение, скажем, не более 32 байт на стеке. Если не умещаются, то «добро пожаловать в кучу».

Понятное дело, что это специфика Си++. В том же Rust это, скорее всего, сделано немного по-другому.

Замыкания там тоже создаются на стеке, но вот на счет FnOnce/Fn/FnMut/FnBox я сильно не уверен, что они при боксинге сразу не помещаются в кучу (это будет некий аналог std::function).

Ведь тебя интересуют языки без GC

dave ★★★★★ ()
Последнее исправление: dave (всего исправлений: 1)
Ответ на: комментарий от dave

Ну, мне не понять, почему для обычного объекта у пользователя есть выбор, создавать его на стеке или в куче, а для замыкания нет.

den73 ★★★★★ ()
Ответ на: комментарий от den73

Для вдобства.

Вся эта пурга с замыканиями по сути магический способ передать операцию сравнения в функцию сортировки, ну или что-то типа этого. Выделение в куче подразумевает более сложные случаи, жизнь замыкания за пределами фрейма создавшей его функции. Это более опасно, появятся косяки с захватом по ссылке. В общем, легкомысленный синтакс замыканий не очень сочетается с потенциальными проблемами, провоцировать новичков на отстрел ног удобным синтаксом неразумно, если им реально нужен функтор, который будет жить отдельной жизнью, пусть лучше сами напишут, хотя бы будут осознавать как он работает.

khrundel ★★★ ()
Ответ на: комментарий от den73

Выбор есть, но синтаксически он выглядит иначе, чем с объектами. В Си++ неявное преобразование к std::function ведет к потенциальному боксингу и уходу из стека в кучу. В Rust боксинг же явный, и там четко понятно, что находится на стеке, а что живет уже в куче

dave ★★★★★ ()
Ответ на: комментарий от den73

В Rust как раз таки выбор есть, и синтаксис там единообразный для объектов и замыканий.

А в Си++ действительно есть небольшая магия с std::function, которая вроде бы и значение, а значит должна жить на стеке, но с другой стороны, любой мощности замыкания должны к std::function приводиться, а следовательно использование кучи просто неизбежно для больших замыканий

dave ★★★★★ ()
Ответ на: комментарий от den73

Ну, и на всякий случай напомню, что у каждого замыкания свой собственный тип, который отличается от std::function, но в Си++ объект типа замыкания может быть неявно приведен к объекту типа std::function. И пока ты используешь замыкание, скажем, вызывая шаблонную функцию - там будет замыкание на стеке. Привел к std::function - все, получаешь потенциальный уход в кучу.

Зачем так сделали? Понятия не имею

dave ★★★★★ ()
Ответ на: комментарий от dave

Хотя догадываюсь, почему такой костыль изобрели в Си++ с std::function. Не хватает Existentially Quantified Type из Haskell или близкого ему по духу аналога Trait Object из Rust...

А std::function ты можешь тоже поместить в кучу, но зачем?

dave ★★★★★ ()
Ответ на: комментарий от khrundel

Ну, в первом приближении выглядит логично, спасибо! Ставлю галочку. Чего мне не хватало, это поглядеть, что такое std::function и теперь я это сделал. Ставлю галочку.

den73 ★★★★★ ()

замыкания в с++ не нужны. для всего достаточно виртуальных методов или метапрограммирования.

anonymous ()

лямбда это по сути структура с методом ().

переменные которые ты захватываешь тупо копируются в момент создания структуры в её поля(которых ты не видишь, их компилятор нарисует).

ckotinko ☆☆☆ ()
Ответ на: комментарий от ckotinko

Да это понятно (хотя ты не совсем точно говоришь, там есть разные способы захвата). Непонятно было, где живёт эта стр-ра - на стеке или в куче и почему. Теперь стало в достаточной степени понятно.

den73 ★★★★★ ()
Ответ на: комментарий от den73

Непонятно было, где живёт эта стр-ра - на стеке или в куче и почему.

Объектам функторов (или лямбдам) не нужно размещение в куче :-) Члены функтора (или захваченные переменные лямбды) могут быть указателями на нечто в куче :-) Это простая логика такого языка, как цепепе :-)

anonymous ()
Ответ на: комментарий от mv

Ты и сам, наверное, догадываешься, что можно сделать в Лиспе, раз г-на Фарэ знаешь

На Лиспе можно легко написать простейший обработчик HTTP-запросов уровня «Hello World!» на базе незаменимого Hunchentoot, который под минимальной нагрузкой сожрёт пол гигабайта оперативной памяти и не поперхнётся (а может и поперхнётся, если какой-нибудь dynamic-space-size окажется недостаточным) :-) А так, на Лиспе делать можно всё то же самое, что можно сделать на цепепе, кроме драйверов устройств :-) Ну и Лисп нельзя использовать во многих встроенных системах по причине раздутости его рантайма :-)

В стартапном окружении, когда требования каждое утро новые, на плюсах было адово писать. Возможность прогнать тесты через полунерабочий прототип с новой архитектурой, не тратя время на борьбу с компилятором, убедившись в жизнеспособности такого подхода - самое ценное. Т.е. короткий time to market, пиэмы от счастья плачут.

В стартапном окружении сколько человек работает? :-) Если 1-2 - то Лисп использовать можно :-) А если больше, то смогут ли они эффективно работать? :-) В Лиспе, как правило, больше разногласий, чем конструктива :-) Потому что язык слишком мощный :-) И каждый норовит использовать мощь по-разному :-) В цепепе история та же :-) Эта проблема даже привела к вмешательству великого Страуструпа, который работает над C++ Core Guidelines, дабы утихли споры и все принялись генерировать тонны кода на цепепе в стиля аля Страуструп :-) Ну а про open source вообще вопрос :-) Вот пусть будет создан какой-то полезный софт на Common Lisp и выложен на Github :-) Каковы шансы у такого софта обзавестись сообществом, которое его будет развивать? :-) Наверное, около нулевые :-) А у цепепе кода шансов чуть больше (правда, не на много) :-)

Да я вас умоляю, новые обои старый бордель не спасут. Пару новых финтифлюшек плюсовики используют, остальное - Си с классами. Но отлаживать их потёки и коррапты приходят сишники, почему-то.

Я знаю сишников, которые рвали на себе рубаху, и кричали на весь интернет, что они никогда не возьмут в проект цепепе :-) Лол :-) Прошло около года, как эти сишники переобулись и теперь всё больше и больше используют цепепе :-) До них, видишь ли, дошло :-)

Ой, отлично всё просто. У меня даже пример из реальной жизни заготовлен: в одном большом французском банке до сих пор крутится лисповая система, за поддержку которой банк чек на десятку в месяц выписывает.

Всё как обычно - секретные системы с поддержкой секретных программистов :-) В цепепе сообществе тоже часто говорят о том, что библиотеки то хорошие есть, но они только закрытые :-) Лол :-)

Когда в коде случается неприятность, она шлёт автору письмо с энвайронментом, он чинит баг, шлёт обратно емейлом патченный код, который применяется в живом образе и система продолжает с ближайшего рестарта.

Да, это реально удобно :-) Тут Лисп рулит :-) А толку? :-)

anonymous ()
Ответ на: комментарий от mv

Ok, partner.

Вот ты знатный писатель на CLisp->DSL->CHDL->FPGA, шаришь в перформансе. Призываешь плюнуть на плюсцы и просветлиться CL.

И однажды, начитавшись тебя, некий Вася Пупкин, средний программист на C++ под Линукс, пилящий в офисном кресле какое-нить сетевое решение с примесью потоков, думает: «Херасе. Круто. Хочу быть таким же крутым.», просветляется лиспом, курит архитектуру хардвари и сопутствующий дзен.

Потом лезет на какой-нить indeed.com и видит, что в этом самом hft рулит либо тот самый C++, либо до усрачки затюниная Java, либо, что реже, решения на FPGA.

И чо-то не сильно от него хотят лиспа, а вот за этих трех парней готовы предложить более-менее выгодный для Василия оффер.

WaterLine ()
Ответ на: комментарий от WaterLine

С некоторого момента денег становится достаточно, и начинаешь путешествовать, заниматься хобби-другим-третьим, писать на лиспе и делать другие вещи, которые приносят удовольствие, а не профит. Жить начинаешь.

А писать HFT на плюсах - это или обычная для местности зарплата, или необычная, но жизни совсем нет - всё время на работе, всё время стресс. «HFT == деньги» - старая городская легенда.

Василию однозначно лисп освоить нужно, он просто станет лучше программистом, даже если писать на нём за деньги не будет.

mv ★★★★★ ()
Ответ на: комментарий от Kuzy

Если у нее нет параметров замыкания, то это обычный указатель на функцию.

Это никому не интересно :-) Интересна аналогия неявного функтора (лямбды) и функтора, определённого явно :-) А во что там компилятор оптимизирует - в обычный или необычный указатель на функцию - дело двадцать второе :-) Лол :-)

anonymous ()
Ответ на: комментарий от anonymous

в одном большом французском банке до сих пор крутится лисповая система, за поддержку которой банк чек на десятку в месяц выписывает.

Всё как обычно - секретные системы с поддержкой секретных программистов :-)

Назови хоть одну причину по которой банку интересно выкладывать в опенсорс софтину написанную «ad hoc» для конкретного банка.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.