Pull to refresh
2
0
Send message

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

Условный оператор там стоит для проверки. Об этом написано в статье. Мне она была нужна.

А не потому ли условный оператор с вызовом has() понадобился, что remove() не делает то, что в ее названии указано? А делает ту самую "инверсию" x^y вместо логичного и правильного x&~y.

Да и странно считать количество логических операций при этом используя условный оператор и вызов метода. Ясно, что там будет инлайн, да всякие оптимизации компилятора, но вы об этом не говорите.

Да и откуда взялись вообще ваши рассказы в комментариях про производительность? В тексте статьи об этом условии ни слова. И нужно ли вообще беспокоиться о производительности и колличестве логических опреторов в описанной вами задаче? Поэтому повторюсь - чем вас std::bitset не устраивает?

У вас метод reach(), который вызывает remove(), работает правильно только потому, что перед вызовом remove() вы делаете проверку has() на нулевое значение проверяемого бита и не вызываете remove() в этом случае если 0. А в случае когда бит равен 1, remove() его просто инвертирует в 0, как вам и пытаются тут показать, что XOR в remove() неуместен, выпполняет инверсию, и делает не то, что вы ожидаете, хоть и все работает в итоге правильно, но до тех пор, пока кто-то не удалил проверку на 0.

Даже для велосипеда перебор получился. Почему не реализовать легкую обертку над std::bitset или использовать его напрямую? Или я чего-то не понял в условиях задачи?

Все верно, согласен с вами. Подзабыл про этоу особенность shared_ptr. Там при создании shared_ptr генерируется делитер с вызовом правильного деструктора, так как статический тип в тот момент известен, и он сохраняется в ControlObject-е этого shared_ptr. Так что да, будет вызван деструктор ExpandProduct не смотря на то, что базовый класс не имеет виртуального деструктора. Но проблема остается для других типов с менеджметом ресурсов которые не обладают такой особенностью как shared_ptr.

Это не статья, это курсовая работа студента начавшего изучать ООП и С++.

Немного по существу.

1. Тема иммутабельности не раскрыта - зачем она вообще нужна эта иммутабельность? В чем проблема мутабельности?

2. Если уж решили использовать наследование и работаете с объектами ExpandProduct через указатель на базовый класс Product, то позаботьтесь хотябы о виртуальном деструкторе в этом базовом классе, иначе все эти ваши std::shared_ptr<Manufacturer> до лампочки.

А если нужно записать одну строку, но 3-мя независимыми вызовами print/write, тогда что делать, если следовать вашей логике и всегда записывать разделитель строк? (собственно print так и поступает по-умолчанию, а write - нет). Все это разнообразие существует только лишь по-тому, что нет единственного правильного решения во всех случаях. В одном случае print должен выводить строку и завершаеть ее \n, а в другом, нужно несколько вызовов print/write для формирования строки, а только последний с \n, например. В библиотеках разных языков подходят по-разному к тому, как должны вести себя функции ввода-выводы. Это конечно путает, но это не значит, что где-то поступают неправильно, а где-то нет, ибо правильно не существует в этой задаче.

Ну так вы спорите именно с этим.

Вот именно что с этим, а не с тем что вы позже написали, указав кучу ограничений в которых ваше первое утверждение становится справедливым. Вам не кажется, что это манипуляция, нет?

Не надо путать адрес со ссылкой, хотя C++ к такой путанице и склоняет.

Я про адрес на конверте говорил. А адрес в памяти, да, это аспект реализации ссылок и указателей в С++ и ссылки не обязаны быть адресом.

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

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

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

Поясните пожалуйста этот набор слов. Что такое "включение" и "необъектная лямбда"? Это вы снова вводите новую "павильную", на ваш взгляд, терминологию?

Возвращаясь к теме беседы, если объект, на который указывает ссылка, не может быть переприсвоен (т.е. в том числе и разрушен), и сам указатель не может быть переприсвоен, то висячая ссылка не образуется.

Спасибо за разъяснение, но это и так очевидно.

Если вы под ссылкой понимаете только само значение указателя, то да.

Да, под адресом на конверте подразумевают адрес на конверте, а не дом по этому адресу.

Легко может стать висячей, если объект на котрый она указывает разрушен, а ссылка еще жива. Изменяемость/неизменяемость самой ссылки никак на этот факт не влияет.

Что способ выделения памяти (и, в частности, место размещения захваченных по значению переменных) зависит от способа использования значения лямбда-выражения.

Та, собственно, как и любого другого значения, любого другого типа.

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

Так и обычная функция не знает откуда взялась память для ее локальных переменных. Что объясняет эта ваша фраза?

Давайте выражаться корректно. Никакой “лямбды” в C++ нет.

Мдяааа, я плакаль...

А Вы вообще понимаете разницу между лямбда функцией, лямбда выражением и обычной функцией? По-вашему получается, что это все одно и то же.
У лямбды есть состояние, которое создается из списка захвата лямбда выражением, оно же и место определения ее тела, то что справа от = в примерах выше. А то состояние, о котором Вы говорите, при рекурсивных вызовах, которое связывается с телом лямбды, так это локальное сотояние на сетке, стековый фрейм, как и у обычной функции. При рекурсивных вызовах будет 11 одновременно существующих стековых фреймов, разных инстансов, как Вы говорите, а при итеративном их тоже будет 11, но не одновременно, а новый стековый фрейм на каждой итерации. А вот состояние лямбды во всех вариантах будет одно.
Лямбда (замыкание, closure) собственно и отличается от обычной функции, по мимо отсутствия имени, наличием этого самого сотояния создаваемого лямбда выражением в точке его определения.
И да, теория и практическая реализация лямбд в разных языках, удивительно, может существенно отличаться. Вам говорят о том, как это реализовано и работает в С++, а Вы, почему-то, упорно это игнорируете говоря, что Вы не спец в С++. Что Вы тут тогда хотиде донести/доказать? К чему эти сотрясения воздуха?

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

А в чем проблема реализовать оператор присвоения без явного вызова деструктора и получения каких-то утечек? Более того можно использовать swap-идиому для реализации оператора присвоения и, снова же, без явного вызова деструктора.

Например для того, чтобы ограничить способ создания обектов запретив создавать их на стеке, а создавать в куче или кастомным распределителем и вернуть какой нибудь std::unique_ptr/std::shared_ptr. Либо необходимо выполнять дополнительные действия до и/или после создания обекта конструктором, которые, по каким-то пичинам, нельзя выполнить в самом конструкторе - вызвать виртуальную функцию, например. Ну и т.д.

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

Вы все же путаете понятия. Лямбды и std::function это разные вещи. То что std::function медленнее чем некие FastDelegates, возможно, не спрою, не знаю, не сравнивал. Но лямбды тут совершенно не причем.
Лямбды в С++, это, по факту, синтаксический сахар над объектами классов с определенным методом operator()(....). А если лябда без захвата, то это фактически обычная функция на которую можно получить указатель. Что тут может быть жутко медленного? Обычные функторы С++ или просто функции (лямбда без захвата) с теми же накладными расходами, возможностями по оптимизации и производительностью.

1

Information

Rating
Does not participate
Registered
Activity