И чего? Ты тоже считаешь, что он привел примеры "построения протокола обмена данными"? Не, в принципе я понимаю, что практически любые программистские задачи можно натянуть на этот самый протокол, аки презерватив на глобус, только тогда смысл исходной фразы полностью теряется.
Здравствуйте, March_rabbit, Вы писали:
M_>а что, какой-нибудь мегаумный мегаязык способен провести сериализацию объекта с циклическими ссылками?
Это даже MFC умеет
M_>здорово, если так.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, drol, Вы писали:
D>using — это как раз тот самый "нормальный образ". От того что вызов Dispose() "вывалян в синтаксическом сахаре", он не перестаёт быть обычным вызовом метода в нормальном контексте исполнения кода.
D>Деструкторы и финализаторы же вызываются совсем другим макаром.
Финализаторы — да, совсем другим макаром. Но шарпные Dispose при выходе из using-скоупа семантически ведут себя почти так же, как и плюсовые деструкторы по выходу из области видимости переменной. (Не важно, как выходим из скоупа — добравшись до конца, выходя по return в середине или при возникновении исключения.) «Почти» — по тем причинам, что ты назвал. Так, например, Dispose(), будучи обычным методом, вполне может содержать вызовы виртуальных функций, и их поведение будет отличаться от вызова виртуальных функций в плюсовом деструкторе. Потому я и говорю об «аналоге» а не об «эквиваленте».
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, -MyXa-, Вы писали:
MX>>Здравствуйте, Qbit86, Вы писали:
S>>>>А конструктором копирования обязательно нужно не забыть попользоваться.
Q>>>Вот не понимаю я этой фразы. Как так, не забыть?
MX>>Предположу, что имеется в виду, например, передача RefCounter<HugeBitmap> в качестве параметра метода:
Q>Передача владения в метод — не такой уж частый случай.
Статистикой не владею. А в С#, разве, передача владения в метод — не единственно возможный способ? Простите за неграмотность, если что.
Q>Скорее всего, на C++ ваша функция будет выглядеть так: Q>
void foo(bitmap const& b);
Скорее всего. никаких указателей, все жили долго и счастливо.
Q>а не так: Q>
void foo(shared_ptr<bitmap> b);
Почему-же? Он хоть и умный, а всё-таки указатель. Легковесная штука, как итератор например, везде ходит по значению. Чем это отличается от
void foo(bitmap *); // угадай в каком напёрстке объект :xz:
Q>или так: Q>
void foo(shared_ptr<bitmap> const& b);
Сомнительно. Зачем такой огород? Владение всё равно передаётся, как и во втором случае, а букв больше. Всё одно, что:
void foo(bitmap * const&);
Q>правда ведь? Ок, пусть надо передавать именно wrapper.
MX>>using (RefCounter<HugeBitmap> hugeBitmap = new RefCounter<HugeBitmap>(new HugeBitmap())) MX>>{ MX>> foo(hugeBitmap.Clone()); // правильно MX>> //foo(hugeBitmap); // ошибка MX>>} MX>>[/c#]
Q>Похоже, всё-таки наоборот.
Почему-же? Создаём hugeBitmap, счётчик = 1.
в первом случае: клонируем RefCounter, счётчик = 2; передаём в foo; в foo свой using, который уменьшает счётчик; при выходе из foo счётчик = 1; using (внутри которого битмап создавался) вызывает Dispose, счётчик уменьшается до 0, убивается объект.
во втором случае: счётчик = 1; передаём в foo; в foo свой using, который уменьшает счётчик до 0, убивается объект; при выходе из foo счётчик = 0; пытаемся дальше работать с битмапом, а он не живой — пора палочкой его тыкать.
Правильно?
Если не поможет, будем действовать током... 600 Вольт (C)
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>И чего? Ты тоже считаешь, что он привел примеры "построения протокола обмена данными"? Не, в принципе я понимаю, что практически любые программистские задачи можно натянуть на этот самый протокол, аки презерватив на глобус, только тогда смысл исходной фразы полностью теряется.
Ещё раз, медленно: Найк, вроде бы, со мной согласен. Другого источника информации у меня нет.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Eugeny__, Вы писали:
E__>1. Сохранить данные сессий универсальным сериализатором на диск, чтобы после рестарта поднять их и продолжить работу. E__>2. Послать пользователай на###, и просто рестартануться, забив на данные.
3. Разослать приложениям уведомление о том, что сейчас рестарт...
Вдруг на том конце что-то нельзя просто так взять и бросить... TCP\IP соединяния надо бы восстановит после рестарта ну и мало ли что там на другом конце? Может АЭС, например?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>А в ХиндиСи придётся и пользователю объемлющего классу от использования значка = воздерживаться и т. д... ;)
Не придётся, значок по прежнему «=» удобен и всяко полезен. Разве что он право владения не даёт. Например, при передаче аргумента в функцию обработки шарить владение не надо, знай себе, передавай ссылку. Никаких накладных расходов вроде инкремента/декремента. Если же хочешь стать совладельцем (то есть заиметь право вызвать Dispose()) — будь добр, вызови метод.
E>Короче, IMHO? лучше в ХиндиСи парадигму COW не использовать...
Здравствуйте, Qbit86, Вы писали:
Q>Никаких накладных расходов вроде инкремента/декремента. Если же хочешь стать совладельцем (то есть заиметь право вызвать Dispose()) — будь добр, вызови метод.
Вопрос не в накладных расходах, а в том, что тебе снаружи надо знать о том, что находится внутри...
E>>Короче, IMHO? лучше в ХиндиСи парадигму COW не использовать... Q>Чем тебе стандартный System.String не COW?
А оно COW? Разве не GC? В любом случае момент освобождения ресурсов разве детерминирован?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, gandjustas, Вы писали:
G>Вообще говоря в основе такой сериализации лежит алгоритм нахождения связных кусков на графе. G>Если есть нормальные метаданные в языке, то с объектами такое выполняется элементарно.
Можно проще. Хранить в архиве (объекте в памяти) указатели на всё, что в него записали. И перед записью очередного объекта, проверять, а не записан ли он уже? И если таки да, то сериализовать хитрую ссылку назад... То же и с типами. Типа когда тип встречаем впервые -- пишем метаданные, имя, или ещё чего, что там у нас предусмотренно. А потом только ссылки на это описание пишем и всё...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, -MyXa-, Вы писали:
MX>Статистикой не владею. А в С#, разве, передача владения в метод — не единственно возможный способ?
Ты это серьёзно? Ок, что по-твоему значит термин «владение»?
MX>Скорее всего. никаких указателей, все жили долго и счастливо.
Зачем передавать владение в функцию, которая, скажем, просто читает из твоего битмапа? Чтобы просто вернуть владение по выходу из функции? Эта функция вообще, может быть, разработана без знания о всяких boost::shared_ptr.
Q>>
void foo(shared_ptr<bitmap> b);
MX>Почему-же? Он хоть и умный, а всё-таки указатель. Легковесная штука, как итератор например, везде ходит по значению.
Инкремент/декремент на каждый вызов происходит.
Q>>
void foo(shared_ptr<bitmap> const& b);
MX>Сомнительно. Зачем такой огород? Владение всё равно передаётся, как и во втором случае...
Кому здесь передаётся владение?
MX>а букв больше.
Букв больше, да изменений счётчика меньше.
MX>>>using (RefCounter<HugeBitmap> hugeBitmap = new RefCounter<HugeBitmap>(new HugeBitmap())) MX>>>{ MX>>> foo(hugeBitmap.Clone()); // правильно MX>>> //foo(hugeBitmap); // ошибка MX>>>} MX>>>[/c#]
Q>>Похоже, всё-таки наоборот. MX>Почему-же? Создаём hugeBitmap, счётчик = 1. MX>в первом случае: клонируем RefCounter, счётчик = 2; передаём в foo; в foo свой using,
С какой целью в foo свой using? Ты предлагаешь захватывать ресурс во внешней функции (посредством Clone), а освободить его во внутренней (через Dispose посредством using)? Странные представления о дизайне.
MX>Правильно?
Нет. Либо в Foo есть и using, и hugeBitmap.Clone(), либо ни того, ни другого, что вероятнее. Для использования ресурса не обязательно разделять владение им.
Здравствуйте, Erop, Вы писали:
E>Вопрос не в накладных расходах, а в том, что тебе снаружи надо знать о том, что находится внутри... :xz:
Не нужно знать, что там внутри.
E>А оно COW? Разве не GC?
COW — это Copy-on-Write. GC — это Garbage Collector. Ты так построил фразу, будто считаешь COW и GC антонимами.
E>В любом случае момент освобождения ресурсов разве детерминирован?
Для строк — нет. Потому что у них нет других ресурсов, кроме управляемой памяти.
Здравствуйте, Геннадий Васильев, Вы писали:
НС>>И чего? Ты тоже считаешь, что он привел примеры "построения протокола обмена данными"? Не, в принципе я понимаю, что практически любые программистские задачи можно натянуть на этот самый протокол, аки презерватив на глобус, только тогда смысл исходной фразы полностью теряется.
ГВ>Ещё раз, медленно: Найк, вроде бы, со мной согласен. Другого источника информации у меня нет.
Я абстрагировался до определённого уровня, на котором сериализация стала протоколом обмена данными одной структуры данных с другой
Т.е. превращение какой-то сложной структуры данных в другое представление (хмл, бинарный формат, трансформированная структура данных, та же самая структура данных с шарингом нужных данных, опять же сетевой протокол реализовался силами той же реализации сериализации).
Вопрос в том — кто до какого уровня абстрагировался
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, -MyXa-, Вы писали:
MX>>Статистикой не владею. А в С#, разве, передача владения в метод — не единственно возможный способ?
Q>Ты это серьёзно? Ок, что по-твоему значит термин «владение»?
Серьёзно ли я? Да я в зеркале себе не улыбаюсь.
Под владением я понимаю — "кто последний, тот и убирает". А если функция владеет объектом, это значит, что она это право может и передать. Или вот, например, если составные части объекта передают, якобы, на "посмотреть" в функцию, то, возможно, они ещё и переживут своего хозяина:
class почка
{
public int value = 42;
}
class человек1
{
public почка value = new почка();
}
class человек2
{
public почка value = null;
}
static void foo(почка o, человек2 oo)
{
oo.value = o; // заграбастали чужую часть, осталось только первоначального владельца замочить
}
static void Main(string[] args)
{
человек1 o1 = new человек1();
человек2 o2 = new человек2();
foo(o1.value, o2);
В С# есть другие варианты?
MX>>Скорее всего. никаких указателей, все жили долго и счастливо.
Q>Зачем передавать владение в функцию, которая, скажем, просто читает из твоего битмапа? Чтобы просто вернуть владение по выходу из функции? Эта функция вообще, может быть, разработана без знания о всяких boost::shared_ptr.
Незачем. Даже звучит странно. Может.
Q>>>
void foo(shared_ptr<bitmap> b);
MX>>Почему-же? Он хоть и умный, а всё-таки указатель. Легковесная штука, как итератор например, везде ходит по значению.
Q>Инкремент/декремент на каждый вызов происходит.
Да, но за то мы получаем возможность не знать когда именно объект уничтожится.
Q>>>
void foo(shared_ptr<bitmap> const& b);
MX>>Сомнительно. Зачем такой огород? Владение всё равно передаётся, как и во втором случае...
Q>Кому здесь передаётся владение?
Мало ли кому. Нам же отсюда не видно реализацию. Может foo их складирует куда-то.
MX>>а букв больше.
Q>Букв больше, да изменений счётчика меньше.
MX>>>>using (RefCounter<HugeBitmap> hugeBitmap = new RefCounter<HugeBitmap>(new HugeBitmap())) MX>>>>{ MX>>>> foo(hugeBitmap.Clone()); // правильно MX>>>> //foo(hugeBitmap); // ошибка MX>>>>} MX>>>>[/c#]
Q>>>Похоже, всё-таки наоборот. MX>>Почему-же? Создаём hugeBitmap, счётчик = 1. MX>>в первом случае: клонируем RefCounter, счётчик = 2; передаём в foo; в foo свой using,
Q>С какой целью в foo свой using? Ты предлагаешь захватывать ресурс во внешней функции (посредством Clone), а освободить его во внутренней (через Dispose посредством using)? Странные представления о дизайне.
Ровно такими же словами я удивлялся, году в 1999, глядя на одну небезызвестную библиотеку, имя которой превратилось в ругательство. Зачем, думал я, вот это всё делается, о чём Вы говорите. Там увеличили только для того, чтобы при выходе уменьшить. Идиотизм!
Ну, может и странные. А представьте, что у нас плюс ко всему есть ещё и контейнер. Тогда, может получиться, что "Функция foo, не владеющая объектом, прилетевшим к ней в виде параметра, передаёт право владения контейнеру". Технически — возможно, звучит — не красиво.
MX>>Правильно?
Q>Нет. Либо в Foo есть и using, и hugeBitmap.Clone(), либо ни того, ни другого, что вероятнее. Для использования ресурса не обязательно разделять владение им.
Извините, не понимаю — к чему Ваше "Нет", если дальше Вы пишете "Либо в Foo есть и using, и hugeBitmap.Clone()". Я Вам столько букв, а Вы мне — всего три (ну, спасибо, что хоть такие). Где я ошибся — ткните пальцем. Что значит "вероятнее"?
Здравствуйте, -MyXa-, Вы писали:
MX>Почему-же? Создаём hugeBitmap, счётчик = 1.
MX>в первом случае: клонируем RefCounter, счётчик = 2; передаём в foo; в foo свой using, который уменьшает счётчик; при выходе из foo счётчик = 1; using (внутри которого битмап создавался) вызывает Dispose, счётчик уменьшается до 0, убивается объект.
MX>во втором случае: счётчик = 1; передаём в foo; в foo свой using, который уменьшает счётчик до 0, убивается объект; при выходе из foo счётчик = 0; пытаемся дальше работать с битмапом, а он не живой — пора палочкой его тыкать.
MX>Правильно?
Ну уже если навешивать оберток так навешивать Х)
void foo(RefCounter<HugeBitmap> hugeBitmap)
{
...
using (RefCounterScope scope = new RefCounterScope(hugeBitmap)) // Здесь счетчик увеличивается
{
...
} // Здесь уменьшается
...
}
Здравствуйте, Qbit86, Вы писали:
Q>COW — это Copy-on-Write. GC — это Garbage Collector. Ты так построил фразу, будто считаешь COW и GC антонимами.
А, понятно! Я просто привык к такой терминологии, что COW подразумевает совместное владение со счётчиком...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Геннадий Васильев, Вы писали:
LVV>>>>Видимо, множественное наследование ликвидировали из-за наличия озвученных проблем. И сочли за благо ввести отдельную конструкцию. ГВ>>>Каких проблем? LVV>>По этому поводу вспомнилось из его статьи: любая книжка по С++ описывает, как не надо делать при множественном наследовании. Я сам писал — тут он прав... ГВ>Мне такие заявления всегда кажутся излишне самонадеянными. Ну, сам знаешь, нет такой конструкции в языке программирования, которую нельзя было бы применить неправильно.
Естественно. Но в С++ таких уж больно много. Более того, я сейчас общаюсь с оберонцами на их формуме. В Хабаровске один из них, Попков, создал школу юных программистов. Он описывал свой опыт использования С++ для обучения начинающих — те же впечатления. Приходится в основном предупреждать, как не следует делать, чтобы не было лишних проблем.
Когда в С++ погрузился, то это уже на автомате происходит, а для входящих в язык — это настоящая проблема. LVV>>Ну, кое-что подсматриваю и использую. Но небольшие вещи. Типа интеллектуальных указателей. ГВ>На самом деле, там много интересного. Мне сильно понравился boost::spirit — полезная штука для мелких парсеров. И наглядно записывается, и быстро работает. В подробности вдаваться не стал. Ну и по мелочи много всего. boost::bind, boost::function, само собой. Не пойму только, как обстоит дело с boost::channel — будет он когда-нибудь внесён в релиз, или нет.
Да я знаю. Спасибо за подсказку по парсеру — посмотрю, мож включу в учебный курс по системному программированию. А bind и function я смотрел — пришлось студентам в книжке писать: как написать обобщенный алгоритм...
LVV>>Объективно я осенью напишу. Вот сравню БлэкБокс с С++ на одних и тех же задачах — и напишу... ГВ>О-о-о! Это было бы интересно — я про одни и те же задачи.
Я сейчас на С++ проги для книжки по системному ПО пишу. Вот эти проги для освоения ББ и попробую. Там входной язык — компонентный паскаль. Но сама среда — ну очень интересна.
LVV>>Вот раньше был фортран — на нем все и писали... ГВ>А... Да-да. Настоящие программисты работают в NASA и пишут на Фортране. И программы настоящих программистов исполняются в режиме супервизора. Я в курсе.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, Геннадий Васильев, Вы писали: ГВ>И т.д. Короче говоря, могу обращаться со свойством, как с полноценным типом. На C#, насколько я знаю, так поступить нельзя (за исключением использования PropertyInfo, но это несколько иной механизм).
Тебе шашечки или ехать?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
ГВ>Но это мелочи. Гораздо интереснее другое возможное применение. Например, у нас есть класс какого-нибудь развесистого окна с развесистым же управлением, например, свойствами Enabled. Если я могу оперировать свойствами, как отдельными объектами, то я могу написать функцию управления Enabled примерно так (пример сильно упрощённый):
ГВ>Обрати внимание, что эта функция не зависит от типов объектов-носителей самих свойств. Ими могут быть и окна, и какие-нибудь другие классы.
ГВ>Но это ещё не всё. Эту же функцию можно обобщить: ГВ>
ГВ>И после обобщения, например, такую функцию можно легко (если, конечно, мы смогли обобщить ещё и условия) протестировать на другом наборе типов данных, главное, чтобы совпадала семантика чтения и присвоения значений:
bool bOK = false, bool bCancel = false;
someCondition = true; // Это упрощение - я имею в виду, что мы привели тестовое окружение в состояние,
// когда внутреннее условие someCondition станет true.var propOk = (bool b)=>{bOK=b;};
var propCancel = (bool b)=>{bCancel=b;};
ManageEnabled(propOk, propCancel);
TEST_ASSERT(bOK && !bCancel);
otherCondition = true;
ManageEnabled(propOk, propCancel);
TEST_ASSERT(!bOK && bCancel);
someCondition = false;
otherCondition = false;
ManageEnabled(propOk, propCancel);
TEST_ASSERT(!bOK && !bCancel);
ГВ>Само собой, её можно перетаскивать из класса в класс, положить в библиотеку, использовать ещё как-то и т.п.
ГВ>Ну вот, примерно так. На вскидку. Пожалуй, ещё можно добавить, что можно собрать указатели на свойства в массив, ещё как-нибудь использовать. Короче говоря, применять к свойствам полный комплект методов работы с обычными классами.
Когда у тебя в руках молоток — всё кажется гвоздями. Когда С++ — всё кажется классами. Оказывается, не обязательно быть классом для того, чтобы успешно работать.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, -MyXa-, Вы писали:
MX>Под владением я понимаю — "кто последний, тот и убирает". А если функция владеет объектом, это значит, что она это право может и передать. Или вот, например, если составные части объекта передают, якобы, на "посмотреть" в функцию, то, возможно, они ещё и переживут своего хозяина: MX>[Code skipped.] MX>В С# есть другие варианты?
Здесь нет ни передачи владения, ни его разделения. Здесь на одну почку ссылаются два человека. Если любой из них умрёт и вызовет Dispose() для себя и подобъектов, то у другого будет невалидная почка.
Q>>Инкремент/декремент на каждый вызов происходит. MX>Да, но за то мы получаем возможность не знать когда именно объект уничтожится.
Если ты передаёшь boost::shared_ptr по ссылке, то ты тоже этого не знаешь, и при этом у тебя лишний инкремент/декремент не произойдёт. В который раз я это уже повторяю?
Q>>>>
void foo(shared_ptr<bitmap> const& b);
MX>>>Сомнительно. Зачем такой огород? Владение всё равно передаётся, как и во втором случае... Q>>Кому здесь передаётся владение? MX>Мало ли кому. Нам же отсюда не видно реализацию. Может foo их складирует куда-то.
При передаче shared_ptr'а по значению создаётся ещё один совладелец — локальный параметр функции. Вызывается копиктор и инкремент для shared_ptr'а, о чём недвусмысленно свидетельствует use_count(). Здесь же — передача shared_ptr'а по ссылке, дополнительных совладельцев не создаётся, владение не шарится. Так-то.
MX>>>Правильно? Q>>Нет. Либо в Foo есть и using, и hugeBitmap.Clone(), либо ни того, ни другого, что вероятнее. Для использования ресурса не обязательно разделять владение им. MX>Извините, не понимаю — к чему Ваше "Нет", если дальше Вы пишете "Либо в Foo есть и using, и hugeBitmap.Clone()". Я Вам столько букв, а Вы мне — всего три (ну, спасибо, что хоть такие). Где я ошибся — ткните пальцем.
void foo(RefCounter<HugeBitmap h)
{
using (h)
{
// Использование h.
}
}
...
foo(hugeBitmap.Clone());
Такого в природе не бывает. Это всё равно что в плюсовую функцию передать «new int(42)» и внутри сделать «delete p».
MX>Что значит "вероятнее"?
void foo(RefCounter<HugeBitmap h)
{
// Использование h, быть может даже клонирование при необходимости.
}
Здравствуйте, MxKazan, Вы писали:
COF>>Может конечно, это надо специально разруливать — например использовать пару shared_ptr/weak_ptr MK>Вот знаешь, почему хорошо, что в C# нет перегрузки присваивания? Как раз чтобы голова не занималась подсчетом этих операцией или выбором вида указателей. А еще ведь надо будет глядеть не перекрыт ли оператор присваивания, а то мало ли чего на самом деле делается. В C# я всегда знаю, что a = b — есть только копирование указателя в случае ссылочного типа и копирование значения в случае value-типа. Всё четко и ясно. По-моему, это плюс.
По моему, если бы был язык, который поддерживает и сборку мусора и детерминированное освобождение ресурсов, то я бы первый сказал, что этот язык может быть лучше чем C++, а сейчас я могу только повторить, что они разные