С++ - г.., потому что надо думать о памяти, как о ресурсе

kruzer25

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

kokoc88

Пиздец говно эти ваши плюсы.
Когда же разработчику думать о содержательной части, если всё своё время он будет тратить на работу с памятью?
Ты бы хоть в теме разобрался перед наездом, а? написал про ручную работу с памятью через new/delete, так уже давно никто не делает. Или ты думаешь, что в C# нету проблем с ресурсами? Так ты напиши функцию, которая что-то читает из файла. Либо сам убедишься, либо мы тебе продемонстрируем, где у тебя утечки ресурсов на C#.

kruzer25

Так ты напиши функцию, которая что-то читает из файла
Вроде бы, это должно быть что-то вроде
using(fh = File.Open(... {
Console.Write(fh.Read;
}

:smirk:

kokoc88

using(fh = File.Open(... {
Ну тогда твоими же словами, если программист будет всё время думать про using, то когда ему думать про логику программы? Случай с файлом - не единичный. Иногда даже опытные C# программисты забывают написать using при работе с каким-нибудь ресурсом. Например, если ты забудешь написать using при работе с WebRequest/WebResponse, то у тебя может засориться thread pool и программа будет существенно подвисать. А вот в С++ мы не можем забыть закрыть ресурс, потому что деструкторы вызываются автоматически.

kruzer25

1) Ему не надо как-то сильно думать про using. Ему надо про это думать только тогда, когда он создаёт объект IDisposable.
2) Ему надо думать про это только при создании, а у тебя совершенно непонятно где придётся втыкать освобождение ресурсов. Где-то создали объект - значит, надо оборачивать ручками работу с этим объектом в try...catch, ловить все исключения, если что-то поймали - освобождать память и кидать дальше; если ничего не поймали - освобождать память, в результате, код превратится в нечитаемое говно.
А вот в С++ мы не можем забыть закрыть ресурс, потому что деструкторы вызываются автоматически.
В C# - тоже.
Но в c# они вызываются, когда до этих объектов дойдёт сборщик мусора; а в c++, если ты не освободил память явно - только при выходе из программы (или я ошибаюсь?)

ppplva

В C# - тоже.
Но в c# они вызываются, когда до этих объектов дойдёт сборщик мусора
То есть - никогда. Возможно.

kruzer25

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

kruzer25

То есть - никогда
Не позже выхода из программы.
А в C++ когда? По-моему, только при выходе из программы - то есть, даже в худшем случае тогда же, когда и в C#; а в лучшем - гораздо позже.
Кроме того, если ты создал какой-то объект, который больше нигде не хранится - то он, насколько я понимаю, будет удалён сразу, как только пропадёт из области видимости (потому что для этого не нужны сложные алгоритмы, достаточно всего лишь счётчика ссылок).
В C++ же очистка памяти от двух объектов, циклически ссылающихся друг на друга - довольно неприятное занятие.

class Class1 {
private Class2 obj = null;
public void setObj(Class2 obj) { this.obj = obj; }
}

class Class2 {
private Class1 obj = null;
public void setObj(Class1 obj) { this.obj = obj; }
}

В одном месте ты создал экземпляр класса Class1. Затем, совсем в другом месте, где-то в недрах того, что ты позвал из того метода, который создал Class1, в этот объект положили экземпляр класса Class2.
Какое количество геморроя тебе понадобится, чтобы, когда тебе не будет нужен экземпляр Class1, корректно освободить память от обоих экземпляров?

kokoc88

Ему не надо как-то сильно думать про using. Ему надо про это думать только тогда, когда он создаёт объект IDisposable.
Ты знаешь, какое в библиотеках C# количество классов, которые реализуют IDisposable? Их дофига и больше, и каждый раз надо смотреть, что будет, если ты не напишешь using. Кстати, в некоторых случаях он необязателен. Например, Form является IDisposable, но я не видел проектов, где создание модального диалога оборочивают в using. Так что программисту на C# надо думать про using, и ещё как.
Ему надо думать про это только при создании, а у тебя совершенно непонятно где придётся втыкать освобождение ресурсов.
У меня это совершенно понятно. Представь себе, RAII прекрасно работает в Си++. А про память с тобой даже говорить не о чем, ты ведь не имеешь никакого понятия про std::auto_ptr, boost::shared_ptr и boost::weak_ptr.
Но в c# они вызываются, когда до этих объектов дойдёт сборщик мусора; а в c++, если ты не освободил память явно - только при выходе из программы (или я ошибаюсь?)

В Си++ деструкторы вызываются автоматически при выходе объекта из области видимости, при его удалении. Никто из людей, с которыми я работал над Си++ проектами последние пять лет, не освобождал память (и не только память) руками. Я уже не помню, когда последний раз набирал на клавиатуре delete. Так что перед наездами надо сначала разобраться в теме. А то я уже перестал понимать, ты действительно тупой или прикалываешься тут над всеми.

kruzer25

В Си++ деструкторы вызываются автоматически при выходе объекта из области видимости
Что значит "при выходе из области видимости"?
Ты, кстати, так ничего и не ответил насчёт циклических ссылок.
при его удалении
Каком удалении? Для меня "при удалении" означает "при ручном удалении".
boost::someshit
Ага, костыли :D

kokoc88

Не позже выхода из программы.
Да какая разница, что не позже выхода, если клиент открывает 10 окон, они подряд обращаются к БД и начиная с пятого окна не могут завершить асинхронную операцию, потому что маленький thread pool запросов забит незакрытыми соединениями? И не просрутся эти пять окон до тех пор, пока не сработает GC, и все будут думать, что же это за хитрый баг.
? По-моему, только при выходе из программы - то есть, даже в худшем случае тогда же, когда и в C#; а в лучшем - гораздо позже.

В Си++ ровно тогда, когда будет автоматически вызван деструктор. Представь себе, умные дяди додумались даже до того, чтобы вызывать деструкторы при исключениях. Таким образом, ловить исключения мне надо только там, где обрабатывается ошибка.
Какое количество геморроя тебе понадобится, чтобы, когда тебе не будет нужен экземпляр Class1, корректно освободить память от обоих экземпляров?

Одна из спорных тем, но я не считаю её проблемной для Си++. Потому что мне из всего геморроя понадобится только boost::weak_ptr.

kruzer25

Представь себе, умные дяди додумались даже до того, чтобы вызывать деструкторы при исключениях
И как же эти "умные дяди" определяют, какие именно объекты надо уничтожать?
Или твои умные дяди - маги?
Или твои умные дяди на каждом исключении вызывают сборщик мусора, несуществующий в чистых плюсах?
Да какая разница, что не позже выхода, если клиент открывает 10 окон, они подряд обращаются к БД и начиная с пятого окна не могут завершить асинхронную операцию, потому что маленький thread pool запросов забит незакрытыми соединениями?
Как меня научил много лет назад, именно для этого умные люди и придумали IDisposable; и подобные классы должны его имплементить, а работать с этими окнами ты должен через using. Именно потому, что деструктор будет вызван хз когда (и тут тебе язык уже не поможет; наоборот, языки со сборщиками мусора вызывают деструкторы раньше, чем без сборщиков).
Одна из спорных тем, но я не считаю её проблемной
Я бы кинул в тебя картинкой, да не найду её... :(
Ты можешь не считать это проблемой, но на самом деле - это огромная проблема, это самая большая проблема при автоматической чистке памяти.

kokoc88

Что значит "при выходе из области видимости"?
Когда вызываются деструкторы в Си++ ты можешь прочитать в википедии. А гугл наверняка знает, что значит выход из области видимости.
Каком удалении? Для меня "при удалении" означает "при ручном удалении".
Тогда что для тебя значит "ручное удаление"? Ты хоть понимаешь, что можно сказать, что using и деструкторы функционально эквивалентны (разве что деструкторы более универсальны)? Я могу написать программу без единого слова delete и там не будут утекать ни память, ни ресурсы.
Ага, костыли

Костыли у тебя в голове держат твою единственную прямую извилину. boost::smart_ptr входит в новый стандарт Си++, причём почти что с момента появления.

kokoc88

И как же эти "умные дяди" определяют, какие именно объекты надо уничтожать?
Они просто думают головой, а не жопой. Каким образом в Си++ вызываются деструкторы при выбрасывании исключений и к каким проблемам это приводит знают и гугл, и википедия.
Как меня научил много лет назад, именно для этого умные люди и придумали IDisposable; и подобные классы должны его имплементить, а работать с этими окнами ты должен через using. Именно потому, что деструктор будет вызван хз когда (и тут тебе язык уже не поможет; наоборот, языки со сборщиками мусора вызывают деструкторы раньше, чем без сборщиков).
Этот пример был о том, что будет, если кто-то забудет про using. Что случается. А вот про деструктор Си++ программист забыть не может, потому что он вызывается автоматически. И, к сведению, гугл знает, что языки со сборщиками мусора вообще не гарантируют вызов файналайзера. А ты этого не знаешь, но лезешь спорить.
Я бы кинул в тебя картинкой, да не найду её...
Ты можешь не считать это проблемой, но на самом деле - это огромная проблема, это самая большая проблема при автоматической чистке памяти.

Не надо кидать в меня картинкой. Ты мне ещё предложи поработать у вас на "самой удобной в мире панели". Я использую boost::weak_ptr и у меня нет никаких проблем.

kruzer25

Когда вызываются деструкторы в Си++ ты можешь прочитать в википедии
Ссылку.
А гугл наверняка знает, что значит выход из области видимости
Ключевые слова.
Тогда что для тебя значит "ручное удаление"?
Ручной вызов delete.
Ты хоть понимаешь, что можно сказать, что using и деструкторы функционально эквивалентны
Ага, и вообще, любая программа на высокоуровневом языке функционально эквивалентна откомпилированной программе. Давай, пиши свой высокоуровневый проект на ассемблере.
Никакой же эквивалентности для разработчика тут нет.
Одно дело - написать блок using и операции с ресурсом осуществлять внутри этого блока - всё будет замеательно видно, где нужно, будут правильные отступы итд; а в конце будет всего лишь одна закрывающая фигурная скобка.
А другое дело - написать совершенно незаметный среди прочего кода new, а потом ещё в десяти местах расставить такой же незаметный delete, и потом искать, где ресурс освобождается.
Ты ещё предложи
if(...) {
doSomething;
} else {
doSomethingOther;
}

заменить на
if(...);
doSomething;
else;
doSomethingOther;
endif;

А что, функционально ведь то же самое!
boost::smart_ptr входит в новый стандарт Си++,
Новый стандарт Си++, теперь и с вашими любимыми костылями! :D

kruzer25

Каким образом в Си++ вызываются деструкторы при выбрасывании исключений и к каким проблемам это приводит знают и гугл, и википедия.
Ещё скажи "знает интернет".
Ссылки в студию.
Этот пример был о том, что будет, если кто-то забудет про using. Что случается
Это значит, что забывший - неудачник. В плюсах ему будет не легче.
А вот про деструктор Си++ программист забыть не может, потому что он вызывается автоматически.
Ага - автоматически при выходе из программы.
панели
Что тебе не понравилось в этом слове?

kruzer25

Каким образом в Си++ вызываются деструкторы при выбрасывании исключений и к каким проблемам это приводит знают и гугл, и википедия.
Ты же меня тут убеждаешь, что никаких проблем нет, и что в плюсах вообще думать об освобождении ресурсов не надо, всё автоматически будет заебись :smirk:

kokoc88

Ссылку.
Вот ещё, сам найдёшь, если захочешь поумнеть. Здесь один ты не знаешь элементарных вещей.
Ключевые слова.

Ладно, так и быть, помогу инвалиду. Ключевые слова: С++ область видимости
Ручной вызов delete.
Ты хоть читаешь, о чём тебе пишут-то? Современные прикладные программы на Си++ пишут без delete. Посмотри дальше своего носа хоть один раз.
Одно дело - написать блок using и операции с ресурсом осуществлять внутри этого блока - всё будет замеательно видно, где нужно, будут правильные отступы итд; а в конце будет всего лишь одна закрывающая фигурная скобка.
А другое дело - написать совершенно незаметный среди прочего кода new, а потом ещё в десяти местах расставить такой же незаметный delete, и потом искать, где ресурс освобождается.
Ты вообще слушаешь, о чём тебе говорят? Какой delete? Забудь про delete.
Новый стандарт Си++, теперь и с вашими любимыми костылями!

Если называть костылями стандартную библиотеку, то про .NET тебе лучше помолчать. А то иначе, как креслом-каталкой, библиотеку для поддержки C# назвать не сможешь.

deniska



Новый стандарт Си++, теперь и с вашими любимыми костылями!
Зачем ты споришь?
Не только пишет на C++ и не только он прекрасно живет и не пишет delete в своем коде. И не ловит утечек. Наверное так делают большинство программистов на С++. Прямая работа с памятью обычно в универе, в компаниях все работа с памятью скрыта. Команду delete в коде встретить почти не реально, у многих и команд new почти нет. Вся работа с памятью давно обернута в конструкторы и деструкторы. И никто не ищет, куда что пропало. При этом мы вообще без boost обходимся и тоже никаких проблем не испытываем. Я бы даже добавил, что то, как ведет себя занятая память в приложениях на С++ гораздо стабильнее, чем на языках со сборщиками мусора. Если у нас есть требования на программу, что она не может ни в какой момент времени занимать больше 120Мб - то на С++ мы этого можем добиться. А вот как ты будешь контроливровать сборщики мусора - я вообще с трудом понимаю. Тем более в момент сборки почему-то обычно еще и процессор занят немного не тем, что хотят от нашей программы. Заказчикам часто интересно не среднее время работы, а максимальное, и когда в какой-то момент начнется долгая сборка, занимающая часть процессороного времени, можно легко вылететь за ограничения на время.

kokoc88

А вот про деструктор Си++ программист забыть не может, потому что он вызывается автоматически.
--------------------------------------------------------------------------------
Ага - автоматически при выходе из программы.
Пенартур - ты уебан. Вот тебе программа, кури, пока не поймёшь, почему "2" напечатается перед "1". Выход из программы-то после печати "1".

#include <iostream>

class C
{
public:
~C
{
std::cout << "2" << std::endl;
}
};

int main(int, char*[])
{
{
C c;
}
std::cout << "1" << std::endl;
return 0;
}

kokoc88

Ты же меня тут убеждаешь, что никаких проблем нет, и что в плюсах вообще думать об освобождении ресурсов не надо, всё автоматически будет заебись
О каких проблемах я говорил ты сможешь найти в гугле. Форум и пользователи "лучшей в мире панели" в тебя верят.

kruzer25

Вот ещё, сам найдёшь
"Ты неправ, и это можно подтвердить - про то, что твои утверждения неверны, якобы знают и гугл, и википедия! Но ключевые слова для поиска я тебе не скажу, потому что не знаю. Захочешь, сам найдёшь" :smirk:
С++ область видимости
Спасибо, всё стало понятно, не видит дальше своего носа, и считает, что, если переменная определена, например, в каком-нибудь методе - то после выхода из этого метода она нигде не используется.
Если называть костылями стандартную библиотеку
Это смотря с какой стороны посмотреть.
Был дико убогий C++. А потом к дико убогому C++ придумали убогие костыли, чтобы хоть как-то компенсировать убогость C++. После того, как появились эти костыли (лет через 20 после появления самого С++ кто-то решил их включтиь в новый стандарт С++, чтобы всё смотрелось не так убого.
От этого костыли костылями быть не перестают.
то про .NET тебе лучше помолчать
Не угадал.
Вот если бы C# двадцать лет существовал без BCL и дженериков, как и других жизненно необходимых вещей, а потом в Новом Стандарте ТМ их бы прикрутили в виде костылей - они были бы костылями.

kruzer25

Тот же вопрос к тебе - что делать с циклическими ссылками?

kruzer25

Вот тебе программа, кури, пока не поймёшь, почему "2" напечатается перед "1".
А теперь скажи мне, что будет, если C положится куда-то ещё.
Что будет с циклическими ссылками - они ведь, поди, удалятся только после выхода из программы :smirk:
Или до него - и тогда у нас всё побъётся из-за неверных ссылок.
Или до него и с умом - и тогда у нас всё будет тормозить, потому что выйдет тот же самый сборщик мусора, только в форме костыля.
ЗЫ: Я так и не понял, какого хуя ты приебался к слову "панель"? Больше сказать нечего?

kokoc88

Спасибо, всё стало понятно, не видит дальше своего носа, и считает, что, если переменная определена, например, в каком-нибудь методе - то после выхода из этого метода она нигде не используется.
О, пенартур ещё не знает разницу между ссылочными и структурными типами. Хотя что он, собственно говоря, знает? Ты программу посмотрел, понял, где и как вызываются деструкторы?

kokoc88

Тот же вопрос к тебе - что делать с циклическими ссылками?
Тебе на этот вопрос уже ответили. В Си++ для этого используют boost::weak_ptr. Это же является ключевым словом для поиска в гугле.

kruzer25

О каких проблемах я говорил ты сможешь найти в гугле.
Знаешь что, ? Ты идиот, еблан, и совершенно полностью неправ, потому что нихуя не понимаешь.
Подтверждение этого можешь найти в гугле. Сам догадайся, что там искать.

kruzer25

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

6yrop

Например, Form является IDisposable, но я не видел проектов, где создание модального диалога оборочивают в using.

гыыы, лол :grin: Видимо, ты не видел нормальных проектов на C# :grin:. Если у Form не вызывать Dispose, то идет утечка девкрипторов, а они, действительно, кончаются, это несложно воспроизвести.

kokoc88

А теперь скажи мне, что будет, если C положится куда-то ещё.
Для него, представь себе, вызовется конструктор копирования! Переходим ко второму упражнению, что выдаст на экран эта программа? Подсказка: выдаёт 2, 2, 1. И опять 1 после 2, как же так?
#include <iostream>

class C
{
public:
~C
{
std::cout << "2" << std::endl;
}
};

C f
{
C c;
return c;
}

int main(int, char*[])
{
f;
std::cout << "1" << std::endl;
return 0;
}

Что будет с циклическими ссылками - они ведь, поди, удалятся только после выхода из программы

Боюсь, что уровень твоего интеллекта не позволяет тебе пока что понять, что к чему у нас с кольцевыми указателями. Как только пройдём азы, я тебе покажу, что будет с кольцевыми указателями и как правильно на Си++ сделать агрегацию подобную той, что ты написал выше.
ЗЫ: Я так и не понял, какого хуя ты приебался к слову "панель"? Больше сказать нечего?

В гугл, жЫвотное. :) Хотя ладно, ты ведь туда не ходишь... http://musicmp3.spb.ru/info/256131/malenjkaya_devochka_s_paneli.htm

6yrop

Вообще, по идее, редактор должен ругаться на создание IDisposable объекта без явного определения области использования (т.е. без using).
Стандартный враппер класса, реализующего IDisposable, создает объект в конструкторе, и сам реализует IDisposable, и вызывает Dispose объекта в своем методе Dispose.

kokoc88

Такое ощущение, что они вызываются тогда, когда количество ссылок на объект становится равным нулю.
Соответственно, в программах, чуть более сложных твоего примера, такая "чистка памяти" ничего полезного не делает. Может быть, тебе удастся сэкономить несколько процентов, и у тебя с такой "чисткой" памяти будет утекать не десять метров в минуту, а всего-навсего девять с половиной.
Третий урок азов Си++: в этом языке нету подсчёта ссылок.

kokoc88

Видимо, ты не видел нормальных проектов на C# . Если у Form не вызывать Dispose, то идет утечка девкрипторов, а они, действительно, кончаются, это несложно воспроизвести.
Я знаю, к чему это приводит. Я сам участвовал в нормальных проектах, не гони тут. :) И при этом я ни разу не встречал ни кода с using(Form ни проблем с дескрипторами. Видимо, окна у винды заканчиваются намного позже отработок GC.

kokoc88

Знаешь что, ? Ты идиот, еблан, и совершенно полностью неправ, потому что нихуя не понимаешь.
Подтверждение этого можешь найти в гугле. Сам догадайся, что там искать.
penartoor'чег, у тебя проблема в том, что ты лезешь спорить, ничего не зная по теме. Основываясь на том, что кто-то где-то говорит, что в Си++ нет GC, ты лезешь с утверждениями о том, что все должны освобождать память руками. При этом ты совершенно не знаешь, как функционирует этот язык.

6yrop

Видимо, окна у винды заканчиваются намного позже отработок GC.
У нас в проекте было место, в котором мы поленились (точнее поставили туду и отложили) корректно вызывать диспоуз у форм. Я сам реально наблюдал, что дескрипторы заканчиваются, когда подолгу (но не сильно долго) работал с нашей прогой. А наши замечательные индусские тесторы выявили этот баг при первом же тестировании :).

kruzer25

Для него, представь себе, вызовется конструктор копирования!
Похоже, я не очень хорошо (для адептов плюсов) выразился. Если я ещё куда-то передам ссылку на этот объект (копировать всё целиком при каждом чихе - тут сразу память кончится, и никакая чистка тебя не спасёт; да и времени на это копирование у тебя дофига уходить будет).
Переходим ко второму упражнению, что выдаст на экран эта программа? Подсказка: выдаёт 2, 2, 1.
Успокойся, я уже понял, что ты всегда всё будешь копировать.
Ты тут распинался по поводу объектов окон, подключений итп - их ты тоже копировать собираешься?
А сколько времени твоя программа тратит на копирование, относительно общего времени её выполнения?

kokoc88

У нас в проекте было место, в котором мы поленились (точнее поставили туду и отложили) корректно вызывать диспоуз у форм. Я сам реально наблюдал, что дескрипторы заканчиваются, когда подолгу (но не сильно долго) работал с нашей прогой. А наши замечательные индусские тесторы выявили этот баг при первом же тестировании .
Забавно, как же вы сделали более десятка тысяч окон? Мы стали диспозить вьюхи в проекте на WPF. Кстати, там дескрипторы могут заканчиваться гораздо быстрее, всё-таки они иногда представлют собой directx ресурсы.

kruzer25

Стандартный враппер класса, реализующего IDisposable, создает объект в конструкторе, и сам реализует IDisposable, и вызывает Dispose объекта в своем методе Dispose.
Не понял :crazy:

kruzer25

Третий урок азов Си++: в этом языке нету подсчёта ссылок.
Ага, там ссылки просто бьются :smirk:

6yrop

Забавно, как же вы сделали более десятка тысяч окон?
на одно окно расходуется не один дескриптор, и количество окон не заходило за несколько сотен. У нас проблема была кажется с Panel.

kokoc88

Похоже, я не очень хорошо (для адептов плюсов) выразился. Если я ещё куда-то передам ссылку на этот объект (копировать всё целиком при каждом чихе - тут сразу память кончится, и никакая чистка тебя не спасёт; да и времени на это копирование у тебя дофига уходить будет).
Ты опять плохо выразился. Ссылки у нас работают без проблем, без копирования. Куда тебе нужно передать ссылку/указатель/значение объекта? Куда бы ты не передавал, деструкторы всё равно будут вызываться при выходе переменных из области видимости или при удалении объекта, независимо от выбрасывания исключений. (Педантичным читателям напомню, что я знаю о выбрасывании из деструктора.) Писать руками delete при этом не нужно. Память не утечёт.

kokoc88

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

kruzer25

Куда тебе нужно передать ссылку/указатель/значение объекта?
Я тебе показал примитивный пример - два объекта хранят внутри себя ссылки друг на друга.
Создали один объект, передали его какой-то функции, она создала второй объект с ссылкой на первый, сообщила первому объекту о втором - получили циклические ссылки.
Вышли из функции - и что, удалять второй объект? А ничего, что первый хранит на него ссылку и мб потом будет где-то использовать?
Вышли из того блока, где определили первый объект - а его удалять нельзя, на него точно так же ссылается другой объект.
В результате, уже ни один из этих двух объектов не нужен, а в памяти они хранятся.

6yrop

Стандартный враппер класса, реализующего IDisposable, создает объект в конструкторе, и сам реализует IDisposable, и вызывает Dispose объекта в своем методе Dispose.
Не понял
 

public class StreamWriterWrapper: IDisposable
{
private readonly StreamWriter streamWriter;

public StreamWriterWrapper
{
this.streamWriter = new StreamWriter;
}

public void Dispose
{
streamWriter.Dispose;
}
}

kruzer25

Я же говорю, прежде чем спорить, тебе следует понять хотя бы базовые вещи о предмете спора.
Похоже, что всё-таки тебе стоит понять, что у слов есть и не то значение, которое ты зазубрил вместе с плюсами.
Если тебе надо положить один объект в другой и в третий, то во втором и третьем объектах будут храниться либо новые объекты, копии первого; либо ссылки на первый (или сам этот первый объект - это одно и то же, вопрос терминологии).
Как же у вас может "просто не быть" ссылок? Вы всё-таки по каждому чиху бросаетесь всё копировать?

kruzer25

Я имею в виду, не понял применительно к тому, о чём я говорил.
Или ты про сложности для редактора в таком случае? (Создали StreamWriter просто так, а using написали от StreamWriterWrapper(StreamWriter? Да, непонятно, что с таким хреновым с этой точки зрения кодом делать, об этом я не подумал :(

6yrop

StreamWriterWrapper(StreamWriter?
извини, я сначала не тот кусок кода написал, сейчас поправил. Объект StreamWriter снаруже вообще никак не виден.

6yrop

объект StreamWriter просто нужен для внутренней работы класса.

deniska



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

Прочитай хоть одну книжку по С++ ). Ну или по С. Удаление объекта происходит не тогда, когда на него нет ссылок ). Твои циклические ссылки с освобождением памяти в С++ никак не связаны.

ppplva

Бесплатный цирк Ты вообще хоть раз на плюсах писал, или с теоретических позиций споришь?

kruzer25

В принципе, можно наложить ограничение (их и так много что либо:
1) IDisposable объект создаётся внутри using
, либо:
2) IDisposable объект создаётся внутри динамического метода класса, имплементящего IDisposable; хранится внутри экземпляра этого класса (в this); и явно dispose-ится в dispose. Правда, плохо получается, если его могут создать несколько раз; но это уже похоже на злонамеренный обход проверки, и на это можно забить. А от опечаток поможет.

kokoc88

Я тебе показал примитивный пример - два объекта хранят внутри себя ссылки друг на друга.
Так ты понял или нет, что delete нам не нужен? (Оставим пока что вопрос про кольцевые указатели.)

kruzer25

Прочитай хоть одну книжку по С++
Читал.
Удаление объекта происходит не тогда, когда на него нет ссылок ). Твои циклические ссылки с освобождением памяти в С++ никак не связаны
Я тут уже пару часов пытаюсь получить от кого-нибудь информацию, что произойдёт в случае с циклическими ссылками - ссылки станут указывать в никуда или объекты не удалятся.
Вы мне в разных, независимых постах отдельно говорите, что не произойдёт первого и не произойдёт второго. А что произойдёт?
Я вот не вижу, как могут и ссылки не испортиться, и объекты удалиться.
И прежде, чем что-то писать, стоит прочитать не только конкретный пост, на который отвечаешь, выдранный из контекста, но и всю нить обсуждения. А то получается спор вида XXX: "Очевидно, произойдёт либо А, либо Б. Похоже, что в данном случае произойдёт А"; YYY: "Нифига, А не произойдёт, ты ничего не понимаешь, читай книжки"; XXX: "Понятно, значит произойдёт Б"; ZZZ: "Б не может произойти, прочитай хотя бы одну книжку, прежде чем писать такой бред"; XXX: "То есть, всё-таки произойдёт А?"; YYY: "Ты что, не слушал? А произойти не может!"
Вы спорите с тем, на чём я и не настаиваю; но так и не отвечаете на мой вопрос.

kruzer25

Так ты понял или нет, что delete нам не нужен? (Оставим пока что вопрос про кольцевые указатели.)
Вообще-то, в кольцевых указателях и заключается всё самое интересное.

kruzer25

Ты вообще хоть раз на плюсах писал
Представляешь, писал. Плюсы показали себя полным говном.
Кстати, PHP - так себе, а вот на C# писать - одно удовольствие.

kokoc88

Похоже, что всё-таки тебе стоит понять, что у слов есть и не то значение, которое ты зазубрил вместе с плюсами.
Представь себе, я прекрасно знаю как Си++, так и Java, и C#. И ещё до кучи языков типа Lua и подобных.
Если тебе надо положить один объект в другой и в третий, то во втором и третьем объектах будут храниться либо новые объекты, копии первого; либо ссылки на первый (или сам этот первый объект - это одно и то же, вопрос терминологии).
Как же у вас может "просто не быть" ссылок? Вы всё-таки по каждому чиху бросаетесь всё копировать?
У нас нету ссылочных типов, но у нас есть ссылки и указатели. Чтобы спорить, надо знать предмет спора. Нет, мы не копируем, и не используем delete. Мы используем boost::smart_ptr, хотя уже можно написать std:: tr1 ::shared_ptr
Кстати, вот тебе пример кода уже на C#, просто чтобы объяснить тебе, что бывают ссылочные и не ссылочные типы.
    class Program
{
struct S
{
public int i;
}

class C
{
public int i = 0;
}

static void useClass(C c)
{
c.i = 15;
}

static void useStruct(S s)
{
s.i = 15;
}

static void Main(string[] args)
{
C c = new C;
useClass(c);
S s = new S;
useStruct(s);
Console.WriteLine("c.i=" + c.i + ", s.i=" + s.i);
}
}

kosmopolit70

Я тут уже пару часов пытаюсь получить от кого-нибудь информацию, что произойдёт в случае с циклическими ссылками - ссылки станут указывать в никуда или объекты не удалятся.Вы мне в разных, независимых постах отдельно говорите, что не произойдёт первого и не произойдёт второго. А что произойдёт?Я вот не вижу, как могут и ссылки не испортиться, и объекты удалиться.И прежде, чем что-то писать, стоит прочитать не только конкретный пост, на который отвечаешь, выдранный из контекста, но и всю нить обсуждения. А то получается спор вида XXX: "Очевидно, произойдёт либо А, либо Б. Похоже, что в данном случае произойдёт А"; YYY: "Нифига, А не произойдёт, ты ничего не понимаешь, читай книжки"; XXX: "Понятно, значит произойдёт Б"; ZZZ: "Б не может произойти, прочитай хотя бы одну книжку, прежде чем писать такой бред"; XXX: "То есть, всё-таки произойдёт А?"; YYY: "Ты что, не слушал? А произойти не может!"Вы спорите с тем, на чём я и не настаиваю; но так и не отвечаете на мой вопрос.
C++ обладаешь чудесным свойством. Когда программист хочет, чтобы объекты, ссылающиеся друг на друга удалялись сразу - они удаляются сразу. Когда хочет, чтобы они удалялись, когда не осталось внешних ссылок на них, кроме тех, которыми они друг на друга ссылаются, - они ведут себя именно так. А когда хотят, чтобы они удалялись только при завершении процесса, то они удаляются при завершении процесса. Для того, тобы компилятор угадал, что хочет пользователь, придумали специальные волшебные классы-обёртки, автоприведение типов при вызове функций и переопределение оператора ->. А ты эти волшебные вещи называешь граблями.

kokoc88

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

kruzer25

Кстати, вот тебе пример кода уже на C#, просто чтобы объяснить тебе, что бывают ссылочные и не ссылочные типы.
Я в курсе, что структуры всегда копируются. На то они и структуры.
Ещё, кстати, у структур не бывает конструкторов и деструкторов - странно, правда?
Мы используем boost::smart_ptr, хотя уже можно написать std:: tr1 ::shared_ptr
А на "старом" чистом C++ без всех этих костылей?

deniska



Я тут уже пару часов пытаюсь получить от кого-нибудь информацию, что произойдёт в случае с циклическими ссылками - ссылки станут указывать в никуда или объекты не удалятся.
Вы мне в разных, независимых постах отдельно говорите, что не произойдёт первого и не произойдёт второго. А что произойдёт?
Я вот не вижу, как могут и ссылки не испортиться, и объекты удалиться.
Я понял что тебе не нравится. Но я плохо понимаю твой пример. Точнее, мне кажется, я плохо понимаю твой пример, который для тебя очевиден, по той причине, что ты почти не писал на С++. Что у тебя за объекты? Они лежат в памяти или на стеке? Если в памяти, то мы их держим за смартпоинтеры? Если они ссылаются друг на друга просто, но мы их просто удалим, когда они перестанут быть нам нужны. От наличие в них ссылок друг на друга нам ни жакро, ни холодно. Или у них как раз друг на друга хранятся смартпоинтеры? Тогда в этом случае да, появится рекурсивная зависимость (если во всех промежуточных вопросах стоит правильный ответ но вот я только не понимаю, на фига я бы так стал делать. То есть обычные циклические ссылки - это вообще не проблема. Но если хотеть именно сделать такую зависимость как ты, то да, будет плохо. Но она нужна только для того, чтобы как раз плохо и сделать (ты же не ругаешься, что если 0 / 0 то тебе почему-то не дают 1 в ответе). В таких ситуациях проще просто сделать есть объект, за которым мы следим (и когда он нам больше не нужен - он сам пропадет а он в свою очередь, когда будет уничтожаться, заодно подчистит всю ту память, что тебе была нужна для игр с твоими перекрекстными и циклическими ссылками.

kruzer25

Кстати, если верить википедии, все эти твои boost-ы нифига не включены в стандарт C++, хоть нынешний, хоть будущий. Да, они есть в C++0x, но тут речь идёт о C++, а не о других языках.

oliver11

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

kokoc88

Кстати, если верить википедии, все эти твои boost-ы нифига не включены в стандарт C++, хоть нынешний, хоть будущий. Да, они есть в C++0x, но тут речь идёт о C++, а не о других языках.
:crazy: Если бы ты удосужился прочитать ещё пару предложений, то ты бы понял, что C++0x - это название стандарта для C++, а TR1 - расширение стандартной библиотеки.

kokoc88

Вот если бы C# двадцать лет существовал без BCL и дженериков, как и других жизненно необходимых вещей, а потом в Новом Стандарте ТМ их бы прикрутили в виде костылей - они были бы костылями.
Кстати, это что, означает, что C# 3.0, LIINQ и WPF ты считаешь костылями C#?

kokoc88

Ссылки стоит заменить на указатели и возложить на один из объектов заботу об удалении другого. В Qt именно так и сделано с виджетами.
Понимаешь, он считает, что для этого придётся написать delete руками. Но для того, чтобы ему что-то втолковать, он сначала должен понять, что Си++ сам не считает ссылки, что Си++ автоматически вызывает деструкторы, и так далее. Тогда ему можно будет показать boost::weak_ptr

kosmopolit70

А на "старом" чистом C++ без всех этих костылей?
А ничего, что boost написан на старом чистом C++?

kruzer25

Они лежат в памяти или на стеке?
Хм... а что лежит в стеке? Аргументы функций?
Если в памяти, то мы их держим за смартпоинтеры?
За что?
Если они ссылаются друг на друга просто, но мы их просто удалим, когда они перестанут быть нам нужны. От наличие в них ссылок друг на друга нам ни жакро, ни холодно.
Проблема в том, что там, где нам перестаёт быть нужен второй объект - нам ещё нужен первый, и мы не имеем права удалять второй объект, мы не знаем, может быть, он ещё будет нужен снаружи. Чтобы не удалять такие объекты, нам надо иметь что-нибудь более продвинутое, чем твои области видимости, а именно - счётчик ссылок.
Но этот счётчик ссылок не даст нам удалить первый объект, когда мы выйдем из той области видимости, где он создан - точно так же, как он не дал нам удалить в похожей ситуации второй объект. Значит, нужно иметь что-то ещё более продвинутое, что-то, что сможет обнаруживать такие "острова". А в реальном времени это делать не получится - вот у тебя и вышел традиционный сборщик мусора.
Тогда в этом случае да, появится рекурсивная зависимость (если во всех промежуточных вопросах стоит правильный ответ
Я не очень понял эти промежуточные вопросы, но похоже, что да.
но вот я только не понимаю, на фига я бы так стал делать
...
Но она нужна только для того, чтобы как раз плохо и сделать
Нет. Такие ситуации сами могут возникать в случае сложной модели (когда объекты косвенно ссылаются друг на друга; в этом цикле может быть и не два объекта, а сто и, выходит, как раз в плюсах и будет течь память - в отличие от языков со сборкой мусора, где она (пусть даже никто заранее и не может сказать, когда) всё-таки будет чиститься.
В таких ситуациях проще просто сделать есть объект, за которым мы следим (и когда он нам больше не нужен - он сам пропадет а он в свою очередь, когда будет уничтожаться, заодно подчистит всю ту память, что тебе была нужна для игр с твоими перекрекстными и циклическими ссылками.
Если решать эту задачу хорошо - то легче уж развязать циклические ссылки. То есть, хрен решишь.
А если не очень - то такой объект будет жить очень долго, время его жизни будет сравнимо со временем жизни программы, и никаких особых преимуществ перед "вызовем все деструкторы перед выходом" это не даст.

kosmopolit70

Кстати, никто не в курсе, на чём написан GC, скажем, в mono?

kruzer25

, ты название темы читал?
Да. Я вижу там "C++".
И я тут говорю, что C++ - говно по сравнению с C#. И тут прибегают какие-то непонятные люди и начинают говорить, что какой-то C++0x не так уж и плох. Да ради бога, я вообще без понятия, что это за C++0x такой, но C++ - говно.

kokoc88

я вообще без понятия,
Ключевая фраза. Ты вообще в любой теме без понятия о предмете этой темы, но упорно толкаешь свои мысли. Зачастую у тебя получается весьма смешно.

kruzer25

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

kruzer25

C++0x - это название стандарта для C++
Жжошь.

kokoc88

например, те же джава и сишарп
Так вот, например, плохие стрелки отстреливают себе ноги в Java и C# гораздо чаще. Но в C# в два раза чаще, чем в Java, потому что в нём нет строгой спецификации исключений. Что на мой взгляд является минусом этого языка.

kruzer25

Кстати, это что, означает, что C# 3.0, LIINQ и WPF ты считаешь костылями C#?
LINQ и WPF не исправляют недостатки старых версий, а добавляют новые фишки.
А все эти ваши boost-ы - именно костыли, чтобы на C++ было писать не совсем хреново, чтобы исправить недостатки C++.
Вот дженерики, появившиеся во второй - да, можно назвать костылями. Вот только между первой и второй версиями сишарпа прошли совсем не 25 лет.

kokoc88

C++0x - это название стандарта для C++
Жжошь.
Ну так вот теперь тебе ссылка: http://en.wikipedia.org/wiki/C%2B%2B0x
C++0x is the planned new standard for the C++ programming language. It is intended to replace the existing C++ standard, ISO/IEC 14882, which was published in 1998 and updated in 2003. These predecessors are informally known as C++98 and C++03.

Ещё раз - не лезь спорить с людьми по теме, о которой ты хотя бы не погуглил.

kruzer25

Понимаешь, он считает, что для этого придётся написать delete руками. Но для того, чтобы ему что-то втолковать, он сначала должен понять, что Си++ сам не считает ссылки, что Си++ автоматически вызывает деструкторы, и так далее. Тогда ему можно будет показать boost::weak_ptr
Ещё один читатель.
Я тут уже пару часов пытаюсь получить от кого-нибудь информацию, что произойдёт в случае с циклическими ссылками - ссылки станут указывать в никуда или объекты не удалятся.
Вы мне в разных, независимых постах отдельно говорите, что не произойдёт первого и не произойдёт второго. А что произойдёт?
Я вот не вижу, как могут и ссылки не испортиться, и объекты удалиться.
И прежде, чем что-то писать, стоит прочитать не только конкретный пост, на который отвечаешь, выдранный из контекста, но и всю нить обсуждения. А то получается спор вида XXX: "Очевидно, произойдёт либо А, либо Б. Похоже, что в данном случае произойдёт А"; YYY: "Нифига, А не произойдёт, ты ничего не понимаешь, читай книжки"; XXX: "Понятно, значит произойдёт Б"; ZZZ: "Б не может произойти, прочитай хотя бы одну книжку, прежде чем писать такой бред"; XXX: "То есть, всё-таки произойдёт А?"; YYY: "Ты что, не слушал? А произойти не может!"
Вы спорите с тем, на чём я и не настаиваю; но так и не отвечаете на мой вопрос.

Elina74

чуве, тема с циклическими ссылками обсасывалась на этом форуме как минимум один раз
use search, мать вашу

kokoc88

LINQ и WPF не исправляют недостатки старых версий, а добавляют новые фишки.
А все эти ваши boost-ы - именно костыли, чтобы на C++ было писать не совсем хреново, чтобы исправить недостатки C++.
boost не исправляет никаких недостатков, а добавляет новые фишки. Сегодня нельзя рассматривать язык без его стандартной библиотеки. И говорить о том, сколько лет прошло, тоже нельзя. 25 лет назад ни один компьютер не потянул бы GC от C# или Java, потому что их реализация GC жрёт память. Так что не надо тут ляля разводить.

kosmopolit70

Так вот, например, плохие стрелки отстреливают себе ноги в Java и C# гораздо чаще. Но в C# в два раза чаще, чем в Java, потому что в нём нет строгой спецификации исключений. Что на мой взгляд является минусом этого языка.
Всё дело в том, что плохие стрелки преимущественно считают С++ говном и на нём не пишут. Больше плохих стрелков пишет на C# или Java и поэтому чаще отсрелива.т себе ноги. Но совсем уж плохие стрелки пишут на PHP и умудряются наловить дедлоков в БД при почти нулевой нагрузке.

kruzer25

Ты вообще в любой теме без понятия о предмете этой темы, но упорно толкаешь свои мысли.
Я не толкаю свои мысли о C++0x.
Сюда могут прийти ассенизаторы и начать чего-то говорить о сравнительных характеристиках отбросов в разных городах. Я совершенно не в теме этих отбросов - и что, я не могу что-то говорить по теме треда?
Ты сюда пришёл и начал пороть какую-то хрень про C++0x. Да, я без понятия про этот ваш C++0x, и, заметь - я ничего и не говорю про C++0x, я говорю про чистый C++.

kruzer25

Ну так вот теперь тебе ссылка
И что?
Того факта, что ты жжошь, это не отменяет.

kruzer25

тема с циклическими ссылками обсасывалась на этом форуме как минимум один раз
Только на моей памяти это было раз пять :D

Elina74

Только на моей памяти это было раз пять :D
и что? форумские "теоретики" еще не наигрались?

deniska



Проблема в том, что там, где нам перестаёт быть нужен второй объект - нам ещё нужен первый, и мы не имеем права удалять второй объект, мы не знаем, может быть, он ещё будет нужен снаружи. Чтобы не удалять такие объекты, нам надо иметь что-нибудь более продвинутое, чем твои области видимости, а именно - счётчик ссылок.
Но этот счётчик ссылок не даст нам удалить первый объект, когда мы выйдем из той области видимости, где он создан - точно так же, как он не дал нам удалить в похожей ситуации второй объект. Значит, нужно иметь что-то ещё более продвинутое, что-то, что сможет обнаруживать такие "острова". А в реальном времени это делать не получится - вот у тебя и вышел традиционный сборщик мусора.
Я тебя попытался понять и объяснить. Но ты, похоже, не пытаешься понять что тебе пишут, если там есть места, которые ты не понимаешь. Прочитай лучше пост от mkal, там все предельно ясно. Удаляется ровно тогда, когда надо :)
В С++ наличие на объект ссылки откуда-то не мешает нам его удалить, если мы хотим. Так же в С++ нет твоих умных вещей, как подсчет ссылок. Точнее есть, но не в том понимании, в котором ты используешь. Для простоты картины представь, что у тебя есть ссылки типа А и ссылки типа В. Все свои внутренние перекрестные ссылки ты реализуешь через ссылки типа В. А сами объекты держишь через ссылки типа А. Как только ссылок типо А больше на твои объекты нет - они разом все удаляются, и им насрать на то, что на них ссылаются какие-то ссылки типа В. В С++ указатели бывают разных типов, а не одного. Возможно именно от этого непонимания все вопросы про рекурсивные зависимости.

kokoc88

Ещё один читатель.
В ответ на:
Я тут уже пару часов пытаюсь получить от кого-нибудь информацию, что произойдёт в случае с циклическими ссылками
Я тут уже пару часов пытаюсь понять, ты уяснил, почему не нужен delete или нет? С циклическими ссылками тебе ответили уже несколько раз: мы используем boost::weak_ptr. В случае удержания двух объектов "в воздухе", они цепляются на shared_ptr за поток, что очень похоже на механизм работы Java/C#. Других вариантов не существует, даже в языке с GC не могут быть два объекта, на которые никто кроме этих объектов не ссылается. Если эта ситуация возникает в языке с GC, то они будут собраны; в Си++ эти объекты сразу удалятся. Нет, delete писать не надо.

kruzer25

Больше плохих стрелков пишет на C# или Java и поэтому чаще отсреливают себе ноги.
Чтобы отстрелить ноги на C#, надо целенаправленно пытаться их отстрелить. Люди, отстрелившие себе ноги на C#, получили то, чего хотели. В чём проблема-то?
и умудряются наловить дедлоков в БД при почти нулевой нагрузке
Интересно, что же это за стрелки такие умудряются наловить дедлоков при почти нулевой загрузке?
Вот при относительно существенной нагрузке, когда в каждый момент времени идёт десяток больших транзакций - уже можно. Для этого достаточно всего лишь не подумать о проблеме дедлоков в самом начале разработки проекта; и исправить это можно, хотя это и довольно трудоёмкая задача.

kruzer25

Да вот хз, несмотря на те треды, постоянно появляются какие-то очередные новички, которые с пеной на губах начинают утверждать, какой замечательный язык сиплюсплюс :smirk:

kokoc88

Ты сюда пришёл и начал пороть какую-то хрень про C++0x. Да, я без понятия про этот ваш C++0x, и, заметь - я ничего и не говорю про C++0x, я говорю про чистый C++.
Бля, ты уебан ещё раз. Ты понимаешь, что выше по теме ты назвал C++0x ДРУГИМ ЯЗЫКОМ, отличным от Си++? Это вообще не язык программирования, а просто стандарт для языка Си++.

kokoc88

Чтобы отстрелить ноги на C#, надо целенаправленно пытаться их отстрелить. Люди, отстрелившие себе ноги на C#, получили то, чего хотели. В чём проблема-то?
Хрен тебе. Забыть using очень просто. Ещё проще не заметить, что кто-то где-то кидает исключение. GUI любят этим страдать: классы застревают на промежуточных состояниях. Ты вообще не написал ещё ни одного проекта в релиз, а лезешь с утверждениями.

kosmopolit70

Да, я без понятия про этот ваш C++0x, и, заметь - я ничего и не говорю про C++0x, я говорю про чистый C++.
С++0x состоит из описания ядра языка и его стандартной библиотеки. Стандартная библиотека написана на С++ же. Если тебе в стандартной библиотеке чего-то не хватает, то ты можешь сам это написать или использовать написанное другими. Ядро С++ не обязано включать в себя вещи, которые можно реализовать на С++. Умные указатели, подсчёт ссылок, GC - это вещи, которые можно написать на С++. Их можно было бы включить в стандартную библиотеку (и часть из этого там есть а можно реализовать на С++ самому. Когда стандартную библиотеку стандартизировали в последний раз, вещи из boost, которые ты называешь костылями, были никому не нужны. Сейчас они нужны и в новый стандарт их включат.
То, что стандарт редко обновляется - проблема C++, но это не делает его плохим языком.
Мне, например, посрать на то, что входит в стандартную библиотеку, а что нет, т.к. в нашей фирме она не используется, а всё что нам надо для автоматического контроля памяти и ресурсов у нас реализовано на С++ в виде своей библиотеки.
На С++ можно сделать GC, а на C# - нет. Поэтому в ядре С++ GC нет, а в C# - есть.

kruzer25

Для простоты картины представь, что у тебя есть ссылки типа А и ссылки типа В. Все свои внутренние перекрестные ссылки ты реализуешь через ссылки типа В. А сами объекты держишь через ссылки типа А.
Я понял, что есть два типа ссылок; но мне не нравится, что ты предлагаешь реализовывать потенциально циклические ссылки через тип Б. Некрасиво как-то, когда неожиданно оказывается, что там, где должен был быть объект, его нет.
Возможно именно от этого непонимания все вопросы про рекурсивные зависимости.
Нет, от другого непонимания. От того, что, если у меня в одном объекте хранится другой объект, то я хочу, чтобы в любом методе первого объекта, кроме деструктора, этот другой объект существовал; а для тебя является совершенно нормальной ситуация, когда в любой момент второй объект может удалиться.
Я даже представить не могу, как реализовывать сложную логику с такими допущениями.

kruzer25

С циклическими ссылками тебе ответили уже несколько раз: мы используем boost::weak_ptr.
Насколько я понимаю, при этом у нас второй объект может удалиться тогда, когда первый ещё существует, и где-то используется.
Если эта ситуация возникает в языке с GC, то они будут собраны
Только тогда, когда они нигде не используются.
И GC нужно время на то, чтобы найти такие "острова", на которые никто, кроме них, не ссылается. Ты либо ищешь острова, либо удаляешь абы как (т.е. не удаляешь объекты вообще или удаляешь их, когда ещё используются те, которые на них ссылаются).

kokoc88

Я даже представить не могу, как реализовывать сложную логику с такими допущениями.
Это всё потому, что ты вообще не можешь представить себе сложную логику. В твоём примере всегда должен удерживаться хотя бы один объект. Неважно, Си++ это или C#. Как только оба объекта перестают удерживаться, так оба класса и удаляются. Неважно, Си++ или C#.

kruzer25

Это вообще не язык программирования, а просто стандарт для языка Си++.
Будущий возможный стандарт для языка, очень сильно отличающегося от нынешнего C++ (хотя и образованного от него).
По-моему, этого достаточно для того, чтобы назвать C++0x другим языком.

deniska

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

deniska



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

Ты не понял немного. Все ссылки типа В будут рабочими всегда. Объекты удалятся, когда пропадут все (а не одна) ссыки типа А. То есть когда ни на один из объектов не будет ссылок типа А (извне они разом удалятся. До этого момента они будут существовать.



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

kruzer25

Забыть using очень просто.
Ага, это действительно проблема, как тут уже говорили.
Тем не менее, в С++ простор для выстрелов гораздо шире.
Ещё проще не заметить, что кто-то где-то кидает исключение.
Не надо ничего замечать (кстати, это, имхо, как раз минус джавы - что надо везде эти исключения определять, смысл исключений теряется).
Исключение летит до того места, где знают, как его обработать.
Если где-то находится критичный к изменению состояний код - он оборачивается в try..catch, в catch состояние откатывается и исключение кидается дальше. Для этого не надо смотреть, какие именно исключения могут кинуться посередине и могут ли кинуться вообще.
Ты вообще не написал ещё ни одного проекта в релиз,
На C# - нет.
На управляемом языке со сборкой мусора и исключениями - да.

kokoc88

Насколько я понимаю, при этом у нас второй объект может удалиться тогда, когда первый ещё существует, и где-то используется.
Не может. У тебя всегда есть один объект, который удерживается хотя бы текущим потоком. Этот объект держит все остальные. Один shared_ptr, много weak_ptr - это стандартная практика.
Если эта ситуация возникает в языке с GC, то они будут собраны
--------------------------------------------------------------------------------
Только тогда, когда они нигде не используются.

Перечитай мой пост ещё раз. Я говорил о том, что если возникает ситуация, когда два объекта никем не удерживаются, то независимо от языка они удаляются. Неважно, сейчас или в цикле GC.

deniska



Будущий возможный стандарт для языка, очень сильно отличающегося от нынешнего C++ (хотя и образованного от него).
По-моему, этого достаточно для того, чтобы назвать C++0x другим языком.
Чем он отличается? В boost просто реализовано то, что у большинства и так уже давно есть и реализовано. Эта просто дополнительная библиотека для удобства и многие без проблем живут и без нее.

kruzer25

Это всё потому, что ты вообще не можешь представить себе сложную логику.
Как раз могу, в отличие от тебя.
Хотя ты, видимо, под "сложной логикой" подразумеваешь простую, обёрнутую огромной кучей workaround-ов для ситуации "ой, а объект, который мы хранили, оказывается, уже кто-то удалил".
В твоём примере всегда должен удерживаться хотя бы один объект. Неважно, Си++ это или C#. Как только оба объекта перестают удерживаться, так оба класса и удаляются
Можно поподробнее, как именно это сделано в C++?
А именно, интересует "как только оба объекта перестают удерживаться".
В C++ при выходе из каждой области видимости запускается сборщик мусора? Насколько я понимаю, нет.
Но по твоим словам, именно так и выходит. Как только мы вышли из области видимости для последнего видимого снаружи объекта - какая-то магия понимает, что теперь та тысяча объектов, ссылающихся друг на друга, снаружи не используется, и удаляет их.
Как она это понимает и сколько на это уходит времени?

kokoc88

Не надо ничего замечать (кстати, это, имхо, как раз минус джавы - что надо везде эти исключения определять, смысл исключений теряется).
Исключение летит до того места, где знают, как его обработать.
Если где-то находится критичный к изменению состояний код - он оборачивается в try..catch, в catch состояние откатывается и исключение кидается дальше. Для этого не надо смотреть, какие именно исключения могут кинуться посередине и могут ли кинуться вообще.
Если не надо замечать, то это как раз минус. Ты можешь не знать о том, что вызов какой-то функции, написанной другим программистом где-то глубоко внутри кидает исключения. И поэтому ты не завернёшь простой код в try/catch с поддержкой состояния твоего объекта. А тестеры не протестируют обрыв сети, из-за которого и выкидывается исключение.... И у клиентов всё сдохнет.

kruzer25

именно для нашей задачи просто никакой другой язык не подойдет
В задачах, где крайне критично быстродействие и потребление памяти (например, гамы, создание 3д графики итп C++ действительно лучший язык. Но это "лучший" означает, что C++ всего лишь меньшее зло, и не означает, что C++ - не говно.

kruzer25

Все ссылки типа В будут рабочими всегда. Объекты удалятся, когда пропадут все (а не одна) ссыки типа А. То есть когда ни на один из объектов не будет ссылок типа А (извне они разом удалятся
Всё, понял.

kokoc88

Можно поподробнее, как именно это сделано в C++?
А именно, интересует "как только оба объекта перестают удерживаться".
В C++ при выходе из каждой области видимости запускается сборщик мусора? Насколько я понимаю, нет.
Но по твоим словам, именно так и выходит. Как только мы вышли из области видимости для последнего видимого снаружи объекта - какая-то магия понимает, что теперь та тысяча объектов, ссылающихся друг на друга, снаружи не используется, и удаляет их.
Как она это понимает и сколько на это уходит времени?
Если у тебя тысяча объектов ссылается друг на друга без наличия контейнера для них, то тебе надо убить себя об стену независимо от языка программирования. Если у тебя разумная агрегация, тогда тебе достаточно удерживать один объект извне. Остальные можно удерживать внутри этого объекта. (На древовидной иерархии классов удерживать будут объекты, которые стоят ниже - это хорошее правило.)

kokoc88

Всё, понял.
Ага. И прикинь, мы так ни разу и не написали delete.

kruzer25

Все ссылки типа В будут рабочими всегда. Объекты удалятся, когда пропадут все (а не одна) ссыки типа А. То есть когда ни на один из объектов не будет ссылок типа А (извне они разом удалятся
Есть тысяча объектов, у них друг на друга куча ссылок типа Б.
Кроме того, на один объект снаружи есть ссылка типа А.
Эта ссылка удаляется. Что именно теперь происходит? На то, чтобы понять, что действительно надо что-то удалить, и какие именно объекты надо удалить, по-моему, должна уйти куча времени.

kruzer25

Ты можешь не знать о том, что вызов какой-то функции, написанной другим программистом где-то глубоко внутри кидает исключения. И поэтому ты не завернёшь простой код в try/catch с поддержкой состояния твоего объекта.
Если я что-то вызываю в этом простом коде, и меняю состояние (которое в случае ошибки надо откатить назад) - я оберну простой код в try..catch, и не буду смотреть, кидает сейчас там что-нибудь исключение или нет.

kokoc88

Есть тысяча объектов, у них друг на друга куча ссылок типа Б.
Кроме того, на один объект снаружи есть ссылка типа А.
Эта ссылка удаляется. Что именно теперь происходит? На то, чтобы понять, что действительно надо что-то удалить, и какие именно объекты надо удалить, по-моему, должна уйти куча времени.
Если у тебя тысяча объектов, то они хранятся в контейнере независимо от языка. И удаляться они будут все сразу. Кроме того, реализация CRT в VS2008 создаёт и удаляет объекты быстрее, чем GC в C# 2.0

kruzer25

И прикинь, мы так ни разу и не написали delete.
И, похоже, начали запускать сборщик мусора при каждом выходе из какой-нибудь области видимости.

kokoc88

Если я что-то вызываю в этом простом коде, и меняю состояние (которое в случае ошибки надо откатить назад) - я оберну простой код в try..catch, и не буду смотреть, кидает сейчас там что-нибудь исключение или нет.
То есть ты будешь за этим следить "вручную". Надо это, или не надо - поифигу. А в Java мы будем делать это тогда и только тогда, когда это надо.

kokoc88

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

kruzer25

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

deniska



Эта ссылка удаляется. Что именно теперь происходит? На то, чтобы понять, что действительно надо что-то удалить, и какие именно объекты надо удалить, по-моему, должна уйти куча времени.
Самое интересное, что не надо ). Все происходит мгновенно. Автоматически (а не заметили в какой-то момент, что ссылок больше нет) запускается процесс очищения памяти. Если описывать, как мой пример, то на все объекты есть еще ссылки типа С (которые скрыты и их не видно, они выставляются и убираются автоматически и по ним ясно что именно надо удалить. Они как раз появляются и пропадают вместе с объектом. Если в понятиях , то контейнер заметил, что то, что он хранит, больше никому не надо и просто все удаляет. Кстати, ничто не мешает в таком контейнере иметь совершенно разные по сути объекты.

kokoc88

Тысяча разнотипных, часть из которых может понадобиться в будущем - нет.
Тысяча разнотипных объектов, которые ссылаются друг на друга, имеют базовый класс. Если же ты собрался в каждом из тысячи прописывать конкретные типы, то лучше сразу убей себя об стену. Базовые классы хранятся в контейнере, и далее по тексту. Быстро удалять и создавать контейнеры с объектами Си++ тоже умеет.

oliver11

Базовые классы хранятся в контейнере
Чуть-чуть уточню: указатели на базовые классы. Для хранения указателей в контейнерах в boost даже придумали ptr_{vector, set, ...}.

kruzer25

Мы не запускаем сборщик мусора. У нас его нет. При выходе из области видимости у нас только вызываются деструкторы.
Деструкторы чего?
Для того, чтобы понять, чьи деструкторы вызывать (если вообще надо что-то вызывать) - надо запустить что-то вроде сборщика мусора, чтобы оно увидело, что на такую-то группу объектов существуют ссылки только типа Б.
Кстати, насколько я понимаю, в коде вроде
class CRegistry
...
public void delete(class, id) {
if(isSet(this.hStorage[class][id] unset(this.hStorage[class][id]);
}

в вызове unset (точнее, том, что будет написано вместо этого в плюсах) создастся А-ссылка, затем удалится Б-ссылка, и потом удалится А-ссылка? Или А-ссылок не будет? Во втором случае всё оказывается ещё хуже, "острова" придётся определять ещё чаще.

kokoc88

Чуть-чуть уточню: указатели на базовые классы.
Я выразился обще, потому что говорил про любой язык. :)

kruzer25

Базовые классы хранятся в контейнере
Ага, и ручками всё контролировать :smirk:

kruzer25

контейнер заметил, что то, что он хранит, больше никому не надо и просто все удаляет
Проблема появляется, когда часть объектов никому, кроме их самих, не нужна; а часть - нужна. И никто заранее не знает, что будет нужно, а что - нет.
Можно, конечно, и выстроить тут всё, как надо... но гораздо легче положиться на сборщик мусора.

kokoc88

Для того, чтобы понять, чьи деструкторы вызывать (если вообще надо что-то вызывать) - надо запустить что-то вроде сборщика мусора, чтобы оно увидело, что на такую-то группу объектов существуют ссылки только типа Б.
Для того, чтобы понять, чьи деструкторы вызывать, достаточно лишь раскрутить стек. И ещё деструкторы вызываются во время удаления объекта. Нас это мало волнует. boost::smart_ptr ведёт подсчёт сильных и слабых ссылок сам, в своих деструкторах и конструкторах. Нет, это не ведёт к тормозам или отжиранию памяти.

kokoc88

Ага, и ручками всё контролировать
Время жизни объектов будет контролировать контейнер. Представь себе, он тоже умеет вызывать деструкторы хранимых объектов.

kruzer25

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

kokoc88

Проблема появляется, когда часть объектов никому, кроме их самих, не нужна; а часть - нужна. И никто заранее не знает, что будет нужно, а что - нет.
У тебя что, архитектура программы представляет собой не дерево, а звёздочку? Если "нужная часть" из тысяч объектов, которые ссылаются друг на друга, отдаётся вовне, то ты на самом деле отдаёшь наружу точно такой же контейнер. И если ты будешь работать с этими объектами по одному, без пулинга, то C# начнёт тормозить гораздо раньше, чем Си++.

kruzer25

достаточно лишь раскрутить стек
Причём тут стек?
boost::smart_ptr ведёт подсчёт сильных и слабых ссылок сам, в своих деструкторах и конструкторах.
Есть десять тысяч объектов, у каждого из них - 0 сильных и 10 слабых ссылок. Ну и ещё куча объектов есть, с сильными ссылками.
Как понять, какие объекты из этих десяти тысяч удалять? Как тебе тут поможет твой подсчёт ссылок?
Ты знаешь, что совсем недавно на один объект из этих десяти тысяч была и сильная ссылка, и как раз сейчас её удалили. Как это тебе поможет? Тебе всё равно надо будет потратить немало времени, чтобы понять, что этот объект сейчас находится в острове из тысячи элементов (и каких именно) или что он косвенно всё-таки связан с одним из тех объектов, на которые есть сильные ссылки.

kokoc88

Про то, что получится в случае простого контейнера, который умеет только удалять всё, я уже написал.
Блин, ну ты головой-то подумай. Тебе тут три часа втирали разные умные вещи. Если ты хочешь отрезать кусок графа, то ты его отрежь и верни с другим контейнером. Что на Си++, что на C# одна малина.

oliver11

Про то, что получится в случае простого контейнера, который умеет только удалять всё, я уже написал.
Может я во сне плохо соображаю, но что мешает заюзать контейнер, содержащий shared_ptr?

deniska




Проблема появляется, когда часть объектов никому, кроме их самих, не нужна; а часть - нужна. И никто заранее не знает, что будет нужно, а что - нет.
Я видимо забыл написать, что те объекты, на которые нет ссылок ни типа A ни типа B чудесным образом сами тоже пропадают. Причем в момент, когда пропала ссылка, а не в момент, когда сборшик мусора решит, что пора ему поработать.


... но гораздо легче положиться на сборщик мусора.
и сильно менее надежно ).
PS
У тебя просто немного более узкое понимание, что есть ссылка. Указатели в С++ более свободные. У них есть гибкость, а ты пытаешься привести пример, которые не разрешается в твоих понятиях ссылок при отсутствии сборщика мусора. Если писать немного более низкоуровнево, чем советует Майк, то это нормально, что в некоторые моменты времени ты на часть объектов вообще не хранишь ссылок (в твоем понимании). А потом, когда они нужны, достаешь их из ниоткуда ;)

kokoc88

Причём тут стек?
При том, что для вызова деструкторов не надо считать ссылки. Не путай момент уделения объекта с хипа и вызов деструктора.
Есть десять тысяч объектов, у каждого из них - 0 сильных и 10 слабых ссылок. Ну и ещё куча объектов есть, с сильными ссылками.
Как понять, какие объекты из этих десяти тысяч удалять? Как тебе тут поможет твой подсчёт ссылок?
Ты знаешь, что совсем недавно на один объект из этих десяти тысяч была и сильная ссылка, и как раз сейчас её удалили. Как это тебе поможет? Тебе всё равно надо будет потратить немало времени, чтобы понять, что этот объект сейчас находится в острове из тысячи элементов (и каких именно) или что он косвенно всё-таки связан с одним из тех объектов, на которые есть сильные ссылки.

Десять тысяч объектов - это предмет для пулинга в любом языке. Они хранятся в контейнере и друг на друга указывают голыми указателями. А вообще мы просто берём реализацию графа.
Поэтому давай попроще. Есть два объекта. Один внизу дерева классов, другой вверху. Первый держит shared_ptr на второй. Второй держит weak_ptr на первый. Кто-то держит shared_ptr на первый. Как только удаляется первый, так сразу же удалится второй. Всё. Времени на это тратить не надо.

pitrik2

Всё, понял.
Локс сделал невозможное?

Dasar

На С++ можно сделать GC, а на C# - нет. Поэтому в ядре С++ GC нет, а в C# - есть.
путаешь ms .net и c#.
чего такого нет в C#, что необходимо для написания GC?

bleyman

Блин, ну ты головой-то подумай.
Ты совершенно зря пытаешься говорить с Пенартуром как с нормальным человеком. Если уж на то пошло, ты вообще зря пытаешься говорить с Пенартуром. Это и так довольно бессмысленное времяпрепровождение, а уж обсуждать С++, с которыми он знаком сугубо теоретически...
Я, наверное, имею больше опыта проникновения во внутренний мир ненормальных людей вроде Пенартура и могу для тебя расшифровать его фразу про "тысячу ссылающихся друг на друга разнотипных объектов".
Представь какую-нибудь гуёвую прогу для редактирования чего-нибудь, написанную идиотом. Полным, невозможным, фантастическим идиотом, которого нельзя на километр подпускать к программированию.
Ну, там есть листбокс, ссылающийся на кучу объектов и достающий из них данные, есть какие-то эдит-контролы, тоже ссылающиеся на некоторые из этих объектов, есть кнопки Add, Delete, Import и Export, сотворяющие нечто с объектами. В том числе и с теми же, которые в этот момент редактируются. Некоторые объекты могут иметь ссылки на другие объекты, эти ссылки можно редактировать. Некоторые объекты самостоятельно подписываются на эвенты эдит-контролов.
И нет никакого централизованного лайфтайм менеджера, который следит за тем, чтобы при удалении объекта из общего пула не осталось ссылающихся на него объектов, например. Поэтому через пять минут работы программы в ней накапливается тысяча невидимых из главного листбокса объектов, на которые кто-нибудь ссылается. Ну, текут ссылки, текут. Те же эвенты - подписался, забыл отписаться, всё, ссылка утекла. А может там есть ещё один специальный менеджер для экспорта объектов, который тоже сохраняет ссылки. Некоторые. Случайные, фактически. В самом деле, почему GC позволено вызывать финалайзеры недетерминированно, а программа, недетерминированно сохраняющая объекты в файл, считается глючной? Это дискриминация!
Вот наш милый Пенартурчег, с которым ты зачем-то пытаешься разговаривать как с нормальным человеком, считает, что хороший язык должен позволять построить подобную систему, причём так, чтобы когда наивный юзер редактирует объект, который он по логике уже удалил, всё замечательно продолжало работать, просто при сериализации изменения не сохранились бы. Или сохранились, но тоже в специальном невидимом обычными методами куске графа. А чо, нормально.
Ты, по ходу, даже представить себе не можешь, что кто-то может так видеть мир, поэтому неправильно отвечаешь на его вопросы. У тебя-то есть чёткое представление о том, кто чей хозяин и когда кто удаляется, не столько потому, что ты боишься утечек памяти, сколько потому, что порядок должен быть. Если есть порядок, то, в качестве побочного эффекта, всё удаляется своевременно и ничего никуда не утекает.
Вот, в рамках своего представления ты пишешь что-то про weak_ptr, ну, ты ведь точно знаешь, куда их нужно поставить и что произойдёт. А Пенартур наоборот не может представить, что у кого-то прога может быть упорядочена, и читая твои слова представляет свою тыщу макаронистых объектов, у которых часть сырых пойнтеров зачем-то заменена на бустовские структуры. И, естественно, не понимает, как это поможет избежать... ну, чего-нибудь избежать, короче.

Dasar

Если у тебя тысяча объектов ссылается друг на друга без наличия контейнера для них, то тебе надо убить себя об стену независимо от языка программирования. Если у тебя разумная агрегация, тогда тебе достаточно удерживать один объект извне. Остальные можно удерживать внутри этого объекта. (На древовидной иерархии классов удерживать будут объекты, которые стоят ниже - это хорошее правило.)
в больших проектах, особенно в интеграционных совсем не очевидно, кто будет держать этот самый контейнер, или кто будет держать вышестоящие объекты.
Возьмем, например, Excel или Html Dom, или любой другой объемистый объектный граф - и есть модуль, который работает с частью этого графа.
 какую ссылку этот модуль должен держать - на ту часть с которой работает? на весь DOM?
что-то еще?
Проблема понятна? пояснить?

Dasar

что хороший язык должен позволять построить подобную систему, причём так, чтобы когда наивный юзер редактирует объект, который он по логике уже удалил, всё замечательно продолжало работать, просто при сериализации изменения не сохранились бы.
интернет вроде работает по такой схеме, и ниче живет вроде отлично.
а вот "интернеты" построенные по жесткой схеме почему-то не прижились.
afaik, большие (вернее, БОЛЬШИЕ) проекты невозможно сделать по той централизованной схеме, которую ты предлагаешь.

Dasar

на самом деле, разница между С++ и C# - одна и это то, что память не ресурс, но все остальные ресурсы-то остаются, и остаются все связанные с ресурсами проблемы:
1. ресурс - конечен
2. ресурс - требует детерминированное удаление (следует из п.1)
3. при чистке ресурсов нельзя полагаться на существующие GC (т.к. GC - недетерминирован и п.2)
4. если кто-то использует ресурс - то он сам по себе становится ресурсом (из п.2)
5. при работе с ресурсами приходится использовать метод подсчета ссылок (т.к. бывают ссылки много к одному, и да более сложные методы провисают по скорости, и да нам же нужен п.2)
6. есть проблема с циклическими ссылками (из п. 5)
И все эти проблемы есть и в C#, и в C++, но... большую часть объектов составляют всякие вспомогательные объекты: строки, точки, числа, коллекции, которые используют лишь один вид ресурса - память, соответственно как только память перестает быть ресурсом, то и вся толпа этих объектов тоже перестает быть ресурсами (см. п.4).
итого:
разница между программированием на C++ и C# лишь в том:
что при программирование на C++ приходится постоянно прокручивать в голове, что весь миллион используемых объектов - это ресурсы, и соответственно при каждом чихе проверять все перечисленные 6 пунктов,
на C# тоже необходимо крутить мысли про ресурсы - только уже про десяток-сотню-десятки тысяч основных объектов, и развязывать себе руки при работе с остальным миллионом вспомогательных объектов.
ps
[to penartur]
да, на C# тоже есть проблема с циклическими ссылками.
да, при написании на C++, используя небольшой набор "культурных" правил, можно почти не думать о том, что память это ресурс
[to all]
да, C++ - очень страшный мастодонт и должен умереть (причем отсутствие GC лишь небольшое неудобство на фоне остальных проблем C++)

kokoc88

Возьмем, например, Excel или Html Dom, или любой другой объемистый объектный граф - и есть модуль, который работает с частью этого графа.
какую ссылку этот модель должен держать - на ту часть с которой работает? на весь DOM?
что-то еще?
Проблема понятна? пояснить?
Понимаешь, здесь всё время идёт речь о графах, о представлении данных. (И правильно, если у тебя тяжёлые кольцевые ссылки внутри обычной архитектуры, то такую архитектуру лучше выкинуть на помойку.) А в хорошей архитектуре такие данные хранятся и обрабатываются отдельно, для этого есть много известных механизмов.
При выделении части графа никто тебе не мешает либо отрезать от него кусок и прицепить за shared_ptr, либо оставить его в контейнере и работать с частью этого графа через контейнер, либо взять shared_ptr конкретной вершины и выкинуть ненужные. Неважно, есть ли GC в языке, но если ты работаешь с конкретной вершиной графа, где все объекты связаны, то этот граф не будет удалён до тех пор, пока ты не завершил работу с этой вершиной.
Я не спорю, что граф - это один из немногих примеров, когда GC будет немного удобнее. Но не такой, чтобы кричать на каждом углу об утечках памяти в Си++
Кстати, Excel или DOM - это плохой пример, потому что есть их реализация в COM, где как раз есть проблемы с кольцевыми указателями, из-за отсутствия слабых указателей. Но ведь реализация DOM есть, и работает она не с черепашьей скоростью.

kokoc88

да, C++ - очень страшный мастодонт
Ну кто бы мычал про мастодонтов. C# имеет более чем 75 ключевых слов.

pitrik2

имхо, это надо распечатать и на стенку
может в фак раздела поместить?

Dasar

Но ведь реализация DOM есть, и работает она не с черепашьей скоростью.
если уж зашла речь про DCOM, ты реализацию агрегации на DCOM-е видел?
а ведь ты ранее говорил, что агрегация делается довольно очевидно, и можно обойтись weak_ptr.
ps
вообщем, я только хочу отметить, что одними shared_ptr и weak_ptr в большом проекте не обойтись

Dasar

Ну кто бы мычал про мастодонтов. C# имеет более чем 75 ключевых слов.
я больше не про сам язык, я больше про C++-окружение(необходимость наличия исходников для работы с бинарным модулем, однопроходность, прямой доступ к памяти как основной режим, макросы уровня препроцессора, отсутствие byte-кода и т.д.)
у C++, как у языка, есть всего несколько мелких недостатков (навскидку - не различает, когда имя это класс, а когда переменная, отсутствие всякого мелкого синтаксического сахара и т.д.)

evolet

да, на C# тоже есть проблема с циклическими ссылками.
Да , а какая? Или ты про что-то еще...
я читал Рихтера, там он говорил, что в .NET собщик мусора не использует подсчет ссылок, а размечает "живые" объекты начиная с "корней" (все текущие живые локальные переменные-ссылки во всех потоках, ...). Соответственно, если есть 2 объекта, которые друг на друга ссылаются, но на них уже никто не ссылается, то эти 2 объекта gc не разметит и будет соответсвенно считать "мертвыми".

Dasar

Да , а какая? Или ты про что-то еще...
про что-то еще
форма ссылается на таймер, таймер ссылается на форму - жить будет вечно

Dasar

я читал Рихтера, там он говорил, что в .NET собщик мусора не использует подсчет ссылок
это ты про просто-объекты, а речь шла про объекты-ресурсы
просто-объекты, как я уже выше говорил, ресурсом не являются, и с ними проблем нет.

evolet

я в С# не бум бум, а почему вечно? (если писать не влом)

evolet

это ты про просто-объекты, а речь шла про объекты-ресурсы
ааа, это я помню, что том какая-то засада получается, помнится я для себя сделал вывод, что именно для объектов-ресурсов всегда надо юзать using
а ну тогда ясно :)

evolet

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

bleyman

интернет вроде работает по такой схеме, и ниче живет вроде отлично. а вот "интернеты" построенные по жесткой схеме почему-то не прижились.
---
Не уследил за полётом мысли, поясни, пожалуйста.
Возьмем, например, Excel или Html Dom, или любой другой объемистый объектный граф
---
Я хочу сказать, что какой-то способ контроля за целостностью структуры тебе всё равно понадобится. _Особенно_ если у тебя граф действительно большой и сложный. Это вообще тема отдельного холивара, который уже был когда-то: про fail fast. Нормальна ли ситуация, когда твой отдельный обработчик работает с частью графа, которую кто-то в другом месте уже отрезал от всего графа? Что лучше, если этот обработчик зацепился за неё каким-нибудь weak_ptr и словил эксепшен в такой ситуации, или если всё прошло на вид нормально, но данные безнадёжно рассинхронизировались и это обнаружится на следующий день, когда юзер откроет сохранённый документ и обнаружит, что всё, нажитое непосильным трудом, куда-то пропало?
Не, понятно что есть определённый оптимальный уровень паранойи, и лично для меня он комфортней реализуется на шарпе, но всё же в определённых ситуациях плюсы окажутся если не удобней, то, по крайней мере, не намного неудобней. (в работе с памятью, в смысле!)
большую часть объектов составляют всякие вспомогательные объекты: строки, точки, числа, коллекции, которые используют лишь один вид ресурса - память
---
Только учитывай, что 90% этих объектов, которые в шарпе выделяются в хипе и собираются GC, в плюсах выделяются на стеке или автоматически освобождаются в деструкторе. Тут разве что эффективность страдает в некоторой мере, ну, когда ты в плюсах возвращаешь std::string, например. И то, copy on write по идее эту проблему должен решать.
Кстати! , дай-ка ссылочку в подтверждение того, что "реализация CRT в VS2008 создаёт и удаляет объекты быстрее, чем GC в C# 2.0". Что-то этого не может быть, потому что не может быть никогда, по-моему.

sergeikozyr

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

пиздец говно ваш императивный цешарп, когда вы по-человечески, без индексов, не можете организовать итерацию списка по первым двум элементам. ;)

pitrik2

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

timefim

>когда вы по-человечески, без индексов, не можете организовать итерацию списка по первым двум элементам.
Что это такое? Код в студию.

sergeikozyr

act [x] = x
act [x,y] = x*y
act (x:y:z:xs) = x+(x+y)*z + act (y:z:xs)

Dasar

если на пальцах, то:
таймер регистрируется в "системе", чтобы получать тики, поэтому GC считает, что внешняя ссылка на остров из таймера и формы - есть.
и соответственно, приходится самим думать - когда таймер разрегистрировать из системы.
ps
есть метод, чтобы ссылки на таймер от "системы" не было, но там появляется другая проблема - что таймер будет прибиваться, когда мы этого не хотим.

zya369

penartur, тебе надо срочно написать книжку по программированию!
чтобы посмеяться могли не только юзеры флокала
уверен - это будет бестселлер

kosmopolit70

"Основны панельного билдинга на PHP"

kokoc88

итого:
разница между программированием на C++ и C# лишь в том:
что при программирование на C++ приходится постоянно прокручивать в голове, что весь миллион используемых объектов - это ресурсы, и соответственно при каждом чихе помнить все перечисленные 6 пунктов,
на C# про ресурсы необходимо крутить мысли про ресурсы - только уже про десяток-сотню-десятки тысяч основных объектов, и развязывать себе руки при работе с остальным миллионом вспомогательных объектов.
Если заменить в этом тексте Си++ на Си, тогда он становится верным. Иначе я с тобой не согласен. Какие 6 пунктов надо помнить при программировании на Си++, если пункт 3, например, про GC? Почему я должен думать про пункт 2, если вызов деструктора Си++ и так детерминирован?

kokoc88

если уж зашла речь про DCOM, ты реализацию агрегации на DCOM-е видел?
а ведь ты ранее говорил, что агрегация делается довольно очевидно, и можно обойтись weak_ptr.
ps
вообщем, я только хочу отметить, что одними shared_ptr и weak_ptr в большом проекте не обойтись
Агрегация на COM и агрегация в ООП - это совсем разные вещи.
Агрегация в смысле ООП делается очевидно через weak_ptr.
У меня вот уже второй большой проект на Си++, кстати первый крутится в релизе 24/7/365. И я обхожусь только shared_ptr и weak_ptr.

kokoc88

, дай-ка ссылочку в подтверждение того, что "реализация CRT в VS2008 создаёт и удаляет объекты быстрее, чем GC в C# 2.0".
Ссылочки нет. Написали два проекта. В одном большом цикле создавали массив из объектов, потом заполняли его в другом большом цикле. Тестировать, естественно, в Release. Без инлайна и с CRT проверками работает медленнее.
На самом деле я был удивлён результатом. Это привело к тому, что я несколько раз пробежался по коду. Так вот внутри класса C++ конструировался массив int[16] + for на забитие нулями, в шарпе стоял new int[16]. Я изменил на new int[16] и вызов delete, тогда языки примерно сравнялись. Когда я выкинул все члены классов в обоих языках, тогда Си++ проиграл несколько секунд на миллиардах объектов.

pitrik2

а при чем тут сишарп?
в такой трактовке все императивные языки сосут

sergeikozyr

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

pitrik2

кстати, вот вариант на джава

private double act(List<Double> l) {
if (l.size == 1) {
return l.iterator.next;
}
Iterator<Double> it = l.iterator;
double x = it.next;
double y = it.next;
if (l.size == 2) {
return x * y;
}
double z = it.next;
return x + (x + y) * z + act(l.subList(1, l.size;
}

bleyman

Ты типа отстал от жизни, чувак.

var a = new[] { 1.0, 2.0, 3.0 };

var result = a.Aggregate(new { x = 0.0, y = 0.0, z = 0.0, res = 0.0 }, (a, val) =>
{
a.x = a.y; a.y = a.z; a.z = val;
a.res += a.x + (a.x + a.y) * a.z;
return a;
}).res;

Только у тебя начальные условия неестественные, мне их влом обрабатывать.
Хотя, конечно, мне в последнее время начало не хватать статически типизированных туплов или чего-то в этом роде. Чтобы нормально делать генерик функции с переменным количеством разнотипных параметров и всё такое.
: а, ну так неинтересно, ты что. Создать кучу объектов любой лох может. Веселуха начинается когда ты объекты то создаёшь, то удаляешь, в случайном порядке. Тогда бедный аллокатор начинает бродить по памяти в поисках свободных кусочков, а деаллокатор — пытаться объеденить свежеудалённый кусочек с соседними, если они тоже свободны. И зрелище это печально.

Dasar

Какие 6 пунктов надо помнить при программировании на Си++, если пункт 3, например, про GC? Почему я должен думать про пункт 2, если вызов деструктора Си++ и так детерминирован?
вот эти самые 6 пунктов :)
1. да, обязательно надо использовать смартпоинты
2. да, то что идет в стандартной поставке - это фигня, а не смартпоинты, надо либо брать boost, либо писать свои
3. да, и еще раз, надо обязательно использовать смарт-поинты, т.к. если объект утек, то это навсегда
4. да, есть либы, которые смартпоинты не используют, но вы все равно как-нибудь смартпоинты при использовании такой либы используйте.
5. да, кстати смарт-поинтов - не один вид, а целых три: auto_ptr, shared_ptr, weak_ptr. ок, хорошо два - shared_ptr и weak_ptr, но при стыковке с чужими либами - их скорее всего будет больше, или будут такие же, но со своими названиями
6. да, еще раз на всякий случай, надо обязательно использовать смарт-поинты

sergeikozyr

Это что за уродство? Функциональное программирование глазами создателей цешарпа? Не, мы идём своей дорогой, а вы - туда же, куда и перл.

kokoc88

вот эти самые 6 пунктов
Я ничего не понял. Как то, что ты перечислил, ЗАСТАВЛЯЕТ меня ДУМАТЬ о ресурсах? Лично я о них не думаю, я пишу всё на boost::smart_ptr, который входит в новый стандарт Си++ Тот факт, что смарт поинтеров у нас три не напрягает даже одного нейрона в моём мозгу. В то время как при разработке на шарпе я всё время держу в голове пункт на счёт исключений и using.
Стыковки с чужими либами я даже обсуждать не хочу. Чужие либы в 98% случаев гавно. Это больная тема для любого языка. Впрочем, никаких препятствий использовать смарт поинтеры с чужими либами я не вижу.

Dasar

Стыковки с чужими либами я даже обсуждать не хочу. Чужие либы в 98% случаев гавно. Это больная тема для любого языка.
при использовании C++ я был с тобой согласен.
но при использовании C# почему-то уже нет...
кстати, даже еще в старом дельфи не согласен, что чужие либы - гавно.
как ты думаешь, с чем это связано?

kokoc88

но при использовании C# почему-то уже нет...
кстати, даже еще в старом дельфи не согласен, что чужие либы - гавно.
как ты думаешь, с чем это связано?
1. С разным мнением по поводу того, что такое качественная либа.
2. С тем, что Си++ де факто используют те, кто программирует дома за ужином.
3. С персональными предпочтениями по языку программирования.

Dasar

есть более главные причины:
1. мелкие ошибки в C# или в том же Delphi менее критичны, чем в C++
2. в C# и Дельфи есть нормальная поддержка бинарных либ.

kokoc88

есть более главные причины:
1. мелкие ошибки в C# или в том же Delphi менее критичны, чем в C++
2. в C# и Дельфи есть нормальная поддержка бинарных либ.
Ты уже заговорил про удобство создания либы. Не вижу, почему мне было бы труднее создать Си++ библиотеку, чем C#. Конечно, если есть опыт, так как всегда труднее сделать то, чем ты меньше всего занимался.
Ошибки в Delphi не только критичны, но и достаточно часто встречаются, потому что в нём нет автоматического вызова деструкторов.
Ошибки в C# не приводят ни к чему хорошему. Два с половиной года разработки GUI под DevExpress меня в этом убедили. Возникло непредвиденное исключение, банальный NULL pointer, и GUI класс подвис в неопределённом состоянии, программа выдала диалог "блабла обратитесь к разработчикам" и перестала работать. Бывало, что от таких "менее критичных ошибок" не удавалось даже её закрыть. Конечно, это всё от того, что GUI часто пишут непрофессиональные разработчики. Но с точки зрения конечного пользователя подобный NULL pointer что на Си++, что на C# приводит к одинаковому результату: неработоспособность программы, потеря данных.
Вообще всё это уже вне темы обсуждения. Я так и не понял, почему мне надо думать о каких-то шести пунктах, когда я пишу на плюсах. У нас прекрасно работает принцип RAII, что в блоке кода, что в дереве объектов. Поэтому я склоняюсь к тому, что на C# или Java (в этом языке тяжелее всего) надо всё время думать про ресурсы, а на Си++ не надо. Только не стоит понимать мои слова как абсолютную точку зрения, я понимаю разные аргументы и соглашаюсь, что разные языки не лишены недостатков. Но я просто категорически не согласен с подходом, когда "у C# всё хорошо, а у C++ всё плохо", потому что этот подход лишён смысла.

kruzer25

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

kruzer25

Я видимо забыл написать, что те объекты, на которые нет ссылок ни типа A ни типа B чудесным образом сами тоже пропадают.
Это и так понятно.
Вот только к процитированной тобой фразе отношения не имеет.

pitrik2

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

kruzer25

в .NET собщик мусора не использует подсчет ссылок,
Странно.
Было бы логичнее, если бы использовались оба подхода, во многих случаях подсчёт ссылок тоже сработает, и уж точно он будет быстрее GC.

kruzer25

act [x] = x
act [x,y] = x*y
act (x:y:z:xs) = x+(x+y)*z + act (y:z:xs)
А по-русски?

kruzer25

Чужие либы в 98% случаев гавно
Как же так, ведь C++ рулит!
Это больная тема для любого языка
Представь себе, "98%" - не для любого.

kruzer25

С тем, что Си++ де факто используют те извращенцы, кто программирует дома за ужином.

kruzer25

Возникло непредвиденное исключение, банальный NULL pointer
А разве, если не использовать unsafe-код и аккуратно писать конструкторы, такое может произойти? :o

agaaaa

struct Vector3D
{
public double X, Y, Z;
public static Vector3D operator*(Vector3D vec, double mul)
{
return new Vector3D{ X = this.X * mul, Y = this.Y * mul, Z = this.Z * mul };
}
}

var vec = new Vector3D{ X = 1, Y = 1, Z = 1};
var result = vec * 2.0;

как сделать на хаскеле, чтобы последний оператор работал?

kruzer25

Я хз про хаскель, но то, что ты спрашиваешь - всего лишь синтаксический сахар. Запись вида vec*2.0 ничем принципиально не отличается от vec.getMultipliedBy(2.0 а вот запутать человека, который ожидает совсем другого поведения от * - может.

agaaaa

Собственно он написал про один сахар, я пишу ему про другой.

agaaaa

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

alfadred

Насколько я знаю, в таких случаях используют оператор (*>) или (*.) или еще что-нибудь.

agaaaa

А почему не **. и не ****?
А для перемножения матриц там какой оператор?

alfadred

Потому что это несимметричный оператор
матрицы вроде подходят под стадартный Num

sergeikozyr

Молодец, возьми себе с полочки какашку. Зато у вас хвостовая рекурсия не оптимизируется. А из-за таких вот "перегрузок" ещё геморно делать вычислитель расширений не хвостовых рекурсивных функций.

kokoc88

Как же так, ведь C++ рулит!
В ответ на:
Это больная тема для любого языка
Представь себе, "98%" - не для любого.
Представь себе, для любого.

kokoc88

Я не знаю, какой кусок графа отрезать и что вообще надо что-то отрезать. Я предпочитаю переложить эту заботу на плечи сборщика мусора, а самому заниматься действительно важными вещами.
Не путай понятия. Каким образом сборщик мусора должен догадаться, какие из объектов, которые ссылаются друг на друга ему удалить, а какие ты хотел продолжать использовать? Очевидно, чтобы продолжать использовать только часть этих объектов, тебе бы пришлось удалить ссылки между ними и другими объектами в графе. Что на Си++, что на C# эти задачи абсолютно идентичны.
И вообще пора переводить спор в практическое русло. Напиши-ка нам код этого самого графа, и как ты видишь процесс использования только некоторых из его узлов, и в какой момент времени по-твоему будут удалены неиспользуемые узлы. Короче, код ужасного графа в студию!

kruzer25

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

kruzer25

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

kokoc88

Да. Но ты тут, насколько я понял, предлагаешь затем руками разделять граф на две компоненты, одна из которых мне нужна, а другая - нет. В C# делать это руками мне не нужно.
Ничего я не предлагаю. Я предлагаю точно так же эти объекты отвязать.
А вообще давай поступим проще. Сделаем реализацию графа: ты тупо на C# (ведь там же реализация в лоб рулит, как ты утверждаешь а я на Си++ Дальше создадим... нет не 10к, давай сразу 500к вершин, и рандомом свяжем каждую вершину с десятком других. После чего будем обходить граф вширину 1кк раз. Затем разрежем этот граф на графы, в каждом из которых будет по 10к вершин, ты ведь хотел продолжать работать с "частью вершин". Всю эту логику мы запихаем в функцию, которую будем вызывать в цикле 1к раз. Затем мы сначала убедимся, что в Си++ память никуда не утекла. Потом мы убедимся, что время работы тупо написанной (а ты именно так предлагаешь делать граф) программы на C# просасывает программе на Си++. И ещё мы поймём, что C# отжирает памяти в десятки раз больше. Мне просто очень интересно, куда тогда денутся твои аргументы в пользу невзъебенной крутости C#?
Давай напишем код, а то спор без практической основы с неграмотным человеком, мне начал уже надоедать.

kokoc88

Возникло непредвиденное исключение, банальный NULL pointer
А разве, если не использовать unsafe-код и аккуратно писать конструкторы, такое может произойти?
А разве ты хотел о чём-то думать, пока программируешь? NULL pointer exception - самое, наверное, частое исключение, которое летит в программах на C#/Java.

kokoc88

Нет. Только для тех языков, где даже гуру, задумавшийся о чём-то другом в неподходящий момент, случайно выстрелит себе в висок.
Себе в висок ты выстрелишь на любом языке. Ни один язык тебя не спасёт от ошибок, Си++ тут совершенно не при чём. Если ты этого не понимаешь, то это означает, что ты не выполнил ни одного серьёзного проекта. Из моего опыта работы, память начинает утекать в программах на языках с GC раньше и такие проблемы там встречаются чаще, чем на Си++, потому что новички всерьёз рассчитывают, что язык программирования спасёт их от всех бед.

kruzer25

NULL pointer exception - самое, наверное, частое исключение, которое летит в программах на C#/Java.
Можно пример, когда указанные мной условия соблюдены и летит этот самый null pointer exception?
Мне что-то ничего, что может его породить, в голову не приходит.

kruzer25

Сделаем реализацию графа
Ага, а ещё лучше - рассмотрим шарообразного коня в вакууме.

pitrik2

а: ты тупо на C# (ведь там же реализация в лоб рулит, как ты утверждаешь а я на Си++ Дальше создадим... нет не 10к, давай сразу 500к вершин, и рандомом свяжем каждую вершину с десятком других. После чего будем обходить граф вширину 1кк раз. Затем разрежем этот граф на графы, в каждом из которых будет по 10к вершин, ты ведь хотел продолжать работать с "частью вершин". Всю эту логику мы запихаем в функцию, которую будем вызывать в
ой
а сделайте плиз
хотя бы на с++
очнеь хочется посмотреть как щас на нем пишут

pitrik2

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

aleks058

Утечкой памяти называется увеличение времени жизни объекта, из-за того, что кто-то держит на него ссылку, но ты не знаешь, кто.
PS. Не волнуйся, маленький опыт поддаётся увеличению! ;)

pitrik2

вощем как-то так
утильзы для синтаксического сахара

package patternargs;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* @author Mikhail Evdokimov
*/
public class PatternArgsUtils {

public static <T> T invokePatternArgs(Object obj, Object... args) throws Exception {
String methodName = (String) args[0];

Object[] patternArg;
if (args.length == 1) {
patternArg = new Object[0];
} else if (args.length == 2) {
patternArg = (Object[]) args[1];
} else {
throw new InternalError("Support for simple args in the beginning is not yet implemented");
}

// TODO check method for every i
if (patternArg.length == 0) {
Method m = obj.getClass.getMethod(methodName);
return (T) m.invoke(obj);
}

if (patternArg.length == 1) {
Method m = obj.getClass.getMethod(methodName, patternArg[0].getClass;
return (T) m.invoke(obj, patternArg[0]);
}

if (patternArg.length == 2) {
Method m = obj.getClass.getMethod(methodName, patternArg[0].getClass patternArg[0].getClass;
return (T) m.invoke(obj, patternArg[0], patternArg[1]);
}

Method m = obj.getClass.getMethod(methodName, patternArg[0].getClass
patternArg[0].getClass patternArg[0].getClass patternArg.getClass;

Object[] dest = (Object[]) Array.newInstance(patternArg[0].getClass patternArg.length - 3);
if (dest.length > 0) {
System.arraycopy(patternArg, 3, dest, 0, patternArg.length - 3);
}

return (T) m.invoke(obj, patternArg[0], patternArg[1], patternArg[2], dest);
}

public static <T> T[] arr(T x1, T x2, T[] xs) throws Exception {
List<T> l = new ArrayList<T>(2 + xs.length);
l.add(x1);
l.add(x2);
l.addAll(Arrays.asList(xs;
return l.toArrayT[]) Array.newInstance(x1.getClass 2 + xs.length;
}

}

вот решение той задачи

package test;

/**
* @author Mikhail Evdokimov
*/
public interface iAct {
Double act(Double... l) throws Exception;
}

package test;

import static patternargs.PatternArgsUtils.arr;
import static patternargs.PatternArgsUtils.invokePatternArgs;

/**
* @author Mikhail Evdokimov
*/
public class Act implements iAct {
public Double act {
return 0d;
}

public Double act(Double x) {
return x;
}

public Double act(Double x, Double y) {
return x * y;
}

public Double act(Double x, Double y, Double z, Double... xs) throws Exception {
return x + (x + y) * z + act(arr(y, z, xs;
}

@Override
public Double act(Double... l) throws Exception {
return invokePatternArgs(this, "act", l);
}

public static void main(String[] args) throws Exception {
iAct act = new Act;

System.out.println("act(2) = " + act.act(2d;
System.out.println("act(2,3) = " + act.act(2d, 3d;
System.out.println("act(2,3,4) = " + act.act(2d, 3d, 4d;
System.out.println("act(2,3,4,5) = " + act.act(2d, 3d, 4d, 5d;
System.out.println("act(2,3,4,5,6) = " + act.act(2d, 3d, 4d, 5d, 6d;
}
}

"C:\Program Files\Java\jdk1.6.0_06\bin\java" -Didea.launcher.port=7535 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA 7.0\bin" -Dfile.encoding=windows-1251 -classpath "C:\Program Files\Java\jdk1.6.0_06\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.6.0_06\jre\lib\jce.jar;C:\Program Files\Java\jdk1.6.0_06\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.6.0_06\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.6.0_06\jre\lib\resources.jar;C:\Program Files\Java\jdk1.6.0_06\jre\lib\rt.jar;C:\Program Files\Java\jdk1.6.0_06\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.6.0_06\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.6.0_06\jre\lib\ext\sunjce_provider.jar;C:\prog\haskell\out\production\haskell;C:\Program Files (x86)\JetBrains\IntelliJ IDEA 7.0\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain test.Act
act(2) = 2.0
act(2,3) = 6.0
act(2,3,4) = 34.0
act(2,3,4,5) = 80.0
act(2,3,4,5,6) = 148.0
Process finished with exit code 0

kokoc88

Можно пример, когда указанные мной условия соблюдены и летит этот самый null pointer exception?
Мне что-то ничего, что может его породить, в голову не приходит.
Какие условия? Ты же тут втираешь, что C# спасает от любых условий. NULL pointer exception может породить код, в котором используется ссылка на класс, значение которой равно NULL. Если ты не писал кода сложнее трёх классов и длиннее 100 строк, то ты конечно этого не поймёшь.

kokoc88

Сделаем реализацию графа
Ага, а ещё лучше - рассмотрим шарообразного коня в вакууме.
Так что, ты согласен, что у тебя получится код, в котором будет так:
Потом мы убедимся, что время работы тупо написанной (а ты именно так предлагаешь делать граф) программы на C# просасывает программе на Си++. И ещё мы поймём, что C# отжирает памяти в десятки раз больше. Мне просто очень интересно, куда тогда денутся твои аргументы в пользу невзъебенной крутости C#?

Если не согласен, то напиши код. Мы посмотрим, какой ты умный, и как C# потянет 500к объектов, которые друг на друга ссылаются. Если ты не можешь написать конкретный код, тогда иди отсюда нафиг и помалкивай о плюсах и минусах языков программирования.

kokoc88

а сделайте плиз
хотя бы на с++
очнеь хочется посмотреть как щас на нем пишут
Кстати, решение в лоб будет проще и лучше всего работать на Java. (Только если ей давать максимальное количество памяти меньше или равное 256мб, странное поведение у JVM.)

evolet

Pre PS че-то я не понял, гонишь ли ты волну на С++... если да, то я хочу сказать кое что в его оправдание
Все правильно, но его (С++) недостатки являются следстием его достоинств, связанных с устремлениями Стауструпа сделать язык, который ни в чем (!) не будет уступать С (в том числе по скорости и по универсальности и т.д.).
> 1. мелкие ошибки в C# или в том же Delphi менее критичны, чем в C++
все верно, в С++ очень легко допрустить нетривиальные ошибки, но вызвано это тем, что язык позволяет сделать одно и тоже десятком разных способов, различающихся мелкими нюансами, соотвественно, если говорить не о типовых случаях, то на нем можно сделать все, на что способна аппаратура
> 2. в C# и Дельфи есть нормальная поддержка бинарных либ.
да и поэтому в больших проектах на С++ вылезают разные ненужные сложности. Но это из-за желания Стауструпа развязать компиляторам руки и не фиксировать стандартом бинарного представления объектов (но мне лично кажется, что с этим он уже переборщил, особенно если учитывать его ратования за рынок плюсовых библиотек)
Поэтому если говорить о ,как я его называю, "попсовом программировании" (формочки, реализация всяких там "бизнес логик" и пр. то C#, конечно, удобнее. Но если есть жесткие требования к техническим характеристикам софта, то имхо без плюсов не обойтись. (все это мое имхо)

Dasar

Сделаем реализацию графа: ты тупо на C# (ведь там же реализация в лоб рулит, как ты утверждаешь а я на Си++
в чем интерес сравнивать решения лобовых задач?
интереснее смотреть на решения задача со сложной логикой.

kokoc88

в чем интерес сравнивать решения лобовых задач?
интереснее смотреть на решения задача со сложной логикой.
Интерес в том, что пенарtoor2 давит на реализацию структуры хранения данных (иначе я не могу назвать граф из 10к+ эдементов) в лоб. Ты, конечно же, понимаешь, что в лоб на C#/Java такую задачу лучше не решать. А я просто хочу поставить засранца на место. :cool: Не будет кода - он окончательно докажет свою несостоятельность.

Dasar

Ты, конечно же, понимаешь, что в лоб на C#/Java такую задачу лучше не решать. А я просто хочу поставить засранца на место.
у меня есть решение - где на C# в лоб(т.е. без оптимизации структур хранения) обрабатывается граф из 10млн. объектов - прога жрет два гига, но работает стабильно.
есть решение на C++(которое пилят уже 4 года) - жрет меньше раза в 4, но раз в пару месяц при изменений условий эксплуатации она валится в корку, из-за провисшего где-нибудь указателя
зы
основные отличия от твоей задачи:
1. объекты в графе разнородные, связи тоже
2. время жизни каждого объекта или связи тоже рандомное
3. есть несколько потоков - которые этот граф меняют/читают
4. есть длинные событийные процессы, которые работают с этим графом

kokoc88

у меня есть решение - где на C# в лоб(т.е. без оптимизации структур хранения) обрабатывается граф из 10млн. объектов - прога жрет два гига, но работает стабильно.
есть решение на C++(которое пилят уже 4 года) - жрет меньше раза в 4, но раз в пару месяц при изменений условий эксплуатации она валится в корку, из-за провисшего где-нибудь указателя
А меня есть сервис 24/7/365 на Си++, который не упал, не потёк и не повис ни разу после релиза и установки десяткам клиентов. (Многопоточный, обслуживает до десятков клиентов и несколько периферийных устройств параллельно.) Написал я его за 2 месяца, плюс неделя на каждое новое периферийное устройство. В то время, как GUI софт из того же проекта, сделанный на C#, пилят уже третий год и всё равно он продолжает приходить в неработоспособное состояние. И что теперь?

Dasar

кстати как ты оформляешь кусок кода, который локально берет из графа объект по week_ptr и что-то с ним делает, при условии что твой кусок кода обязан вызывать какие-то внешние колбаки (например, с информацией о том, что ты объект обработал)?

Dasar

А меня есть сервис 24/7/365 на Си++,
разработчик один?

kokoc88

разработчик один?
У фреймворка один, а поддержку периферии делали ещё человек пять. (Причём никто не убил фреймворк, он поддерживал транзакционность своего состояния и хорошо отделял свою логику от логики периферии.) У каждой GUI странички у нас был тоже один разработчик. Ни о чём это не говорит.

Dasar

пример кода давай на вышеуказанные условия.
на реальном коде все проблемы решений - лучше видны.

timefim

>И что теперь?
То что все решает стоимость разработки. Кучка индусов + C# дешевле одного Гуру++.

kokoc88

пример кода давай на вышеуказанные условия.
На какие условия, какого кода?

Dasar

чужие посты не читаешь что ли?
1. объекты в графе разнородные, связи тоже
2. время жизни каждого объекта или связи тоже рандомное
3. есть несколько потоков - которые этот граф меняют/читают
4. есть длинные событийные процессы, которые работают с этим графом
кстати как ты оформляешь кусок кода, который локально берет из графа объект по week_ptr и что-то с ним делает, при условии что твой кусок кода обязан вызывать какие-то внешние колбаки (например, с информацией о том, что ты объект обработал)?

kokoc88

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

Dasar

тебе тяжело написать три строчки?
аля

var item = graph.getItem(14);
Console.WriteLine("Обработан элемент: {0} у родителя '{1}'", item.Name, item.Parent.Name);
_OnProcessed(item);
Console.WriteLine("Элемент '{0}' у родителя '{1}' обработан и клиенты об этом оповещены",
item.Name, item.Parent.Name);


ps
добавил еще обращение к родителю

kokoc88

тебе тяжело написать три строчки?
Хорошо:

node_ptr node = graph.get_node(14);
std::cout << "Обработан: " << node->get_name << " у родителя (которого в C# мы тоже не проверили на NULL) " <<
node->get_parent->get_name << std::endl;
on_processed(node);
std::cout << "Обработан: " << node->get_name << " и клиеты уведомлены" << std::endl;

Dasar

обращение к родителю добавь еще плиз (как у меня в коде после исправления хочу посмотреть как ты оформляешь именно доступ к week_ptr-ам.
логика node_ptr какая?

kokoc88

обращение к родителю добавь еще плиз (как у меня в коде после исправления хочу посмотреть как ты оформляешь именно доступ к week_ptr-ам.
логика node_ptr какая?
Код выглядит именно так, как я его написал. :) Ничего не могу поделать, здесь в общем-то не нужен доступ к weak_ptr. Про логику node_ptr я ещё не думал, но это shared_ptr<node>

Dasar

т.е. у node на parent тоже будет shared_ptr?

Dasar

у родителя (которого в C# мы тоже не проверили на NULL)
но у меня то будет exception который я перехвачу сверху, а у тебя core dumped
разницу чуешь?

Dasar

std::cout << "Обработан: " << node->get_name << " и клиеты уведомлены" << std::endl;
а здесь где доступ к родителю?

Dasar

у родителя (которого в C# мы тоже не проверили на NULL)
кстати не ленись давай,
свой кусок кода я лишь привел, как пример того, что я хочу видеть.
в нем я знаю кстати несколько сомнительных моментов.
мне интересно видеть именно тот код, который написал бы именно ты в реальном боевом приложении.

kokoc88

но у меня то будет exception который я перехвачу сверху, а у тебя core dumped
разницу чуешь?
Нет, у меня get_parent выкинет исключение.

Dasar

Нет, у меня get_parent выкинет исключение
если нет родителя? на корневом элементе тоже?

kokoc88

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

kokoc88

если нет родителя? на корневом элементе тоже?
Тоже. У нас у обоих код в этом случае выкидывает исключение. Ты можешь придумывать задачи сколько угодно. Все они всё равно будут одинаковыми: либо реализация структуры данных типа граф (которая в бусте у нас уже есть либо агрегация.

Dasar

хорошо пусть будет не родитель, а сосед слева тогда как?

Dasar

и этого соседа слева тоже хочется в onprocessed запихать
там какой ptr будет? week_ptr, shared_ptr?

kokoc88

и этого соседа слева тоже хочется в onprocessed запихать
там какой ptr будет? week_ptr, shared_ptr?
Если ты пихаешь куски графа в коллбэки, то на любом языке туда надо передать и сам граф. Особенно, если ты планируешь пихать это в несколько потоков. На любую удерживаемую вершину тебе будет нужен shared_ptr

Dasar

Ты можешь придумывать задачи сколько угодно
вот блин словоблудие развел, нет чтобы реальный код писать
так будет или как?

shared_ptr<node> node = graph.get_node(14);
week_ptr<node> left = node->get_left;
if (left == NULL)
return;
std::cout << "Обработан: " << node->get_name << " вместе с соседом " <<
left->get_name << std::endl;
on_processed(node, left);
std::cout << "Обработан: " << node->get_name << " вместе с соседом " <<
left->get_name<< " и клиеты уведомлены" << std::endl;

...
class node
{
week_ptr<node> left;
...
}

..
on_processed(shared_ptr<node>& node, shared_ptr<node>&left);

kokoc88

так будет или как?
Не так. Я же не заставляю тебя отказываться от свойств? :) Как оно будет устроено внутри я не знаю. Я не спорю, что при решении в лоб строк на C# будет немного меньше. Или к чему все эти вопросы?
node_ptr left = node->get_left;

kokoc88

shared_ptr<node> node = graph.get_node(14);
week_ptr<node> left = node->get_left;
if (left == NULL)
  return;
std::cout << "Обработан: " << node->get_name << " вместе с соседом " <<
    left->get_name << std::endl;
on_processed(node, left);
std::cout << "Обработан: " << node->get_name << " вместе с соседом " <<
    left->get_name<< " и клиеты уведомлены" << std::endl;

node_ptr node = graph.get_node(14);
node_ptr left = node->get_left;
std::cout << "Обработан: " << node->get_name << " вместе с соседом " <<
(left ? left->get_name : "NULL") << std::endl;
on_processed(node, left);
std::cout << "Обработан: " << node->get_name << " вместе с соседом " <<
(left ? left->get_name : "NULL") << " и клиеты уведомлены" << std::endl;

Dasar

так в итоге и получается, что не понятно теперь когда этот самый node умрет...

kokoc88

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

agaaaa

У вас - это у кого?
На IA-32 - не оптимизируется. А у меня на AMD64 неплохо так оптимизируется.

kruzer25

Какие условия? Ты же тут втираешь, что C# спасает от любых условий
Не от любых.
Похоже, что ты не читал мой пост.
Я там писал, что надо аккуратно вести себя в конструкторах и деструкторах. Не так уж и много, по сравнению с плюсами.

kruzer25

сначала мы подождём кода от пенортура2
Какого кода?
Если ты про написать программу с огромнцым графом и без чего-либо ещё - уже и я, и сказали тебе, что это не представляет никакого интереса, и ни о чём не говорит.
Если же ты хочешь получить реальное приложение со сложной логикой... эти приложения "просто так не делают", а делают под конкретные задачи; и на них уходит куча времени, за пять минут тебе никто ничего не напишет (и ты за пять минут не напишешь аналог на C++).

kokoc88

Я там писал, что надо аккуратно вести себя в конструкторах и деструкторах. Не так уж и много, по сравнению с плюсами.
По сравнению с чем в плюсах? Ты так ничего и не обосновал, кроме того, что ты абсолютно не знаешь языка.

kokoc88

Какого кода?
Если ты про написать программу с огромнцым графом и без чего-либо ещё - уже и я, и сказали тебе, что это не представляет никакого интереса, и ни о чём не говорит.
Если же ты хочешь получить реальное приложение со сложной логикой... эти приложения "просто так не делают", а делают под конкретные задачи; и на них уходит куча времени, за пять минут тебе никто ничего не напишет (и ты за пять минут не напишешь аналог на C++).
Короче, всё ясно. Ты просто пиздобол. Я тебе, можно сказать, в руки сдал все козыри для того, чтобы ты мог обосновать хоть какие-то преимущества C#. Но ты, в силу своей ограниченности, зассал и никому ничего не доказал, кроме своей безграмотности. :smirk: :smirk: :smirk:
PS Графы я сегодня реализовал на трёх языках. В любой реализации меньше 300 строк.
PPS Учи принципы проектирования софта, в правильном приложении со сложной логикой не бывает десятков тысяч объектов, которые друг на друга ссылаются.

kruzer25

Графы я сегодня реализовал на трёх языках. В любой реализации меньше 300 строк
И что? Какое отношение это имеет к реальным задачам?
в правильном приложении со сложной логикой
Понятно, что для тебя - "сложная логика".

kruzer25

По сравнению с чем в плюсах?
Открой мозг и включи глаза.
Да, в C# и Java тоже есть возможность получить Null pointer exception, как и в плюсах.
Чтобы этого не произошло в c#, надо аккуратно вести себя в конструкторах и деструкторах (впрочем, деструкторы, наверное, при наличии IDisposable нафиг не нужны).
Чтобы этого не произошло в плюсах, аккуратно надо себя вести везде. И думать ещё о куче других вещей.

kokoc88

И что? Какое отношение это имеет к реальным задачам?
Самое прямое. Ты не можешь привети даже банальный практический пример кода на языке, от которого ты тут так писаешь кипятком. Этот раздел называется Development, и здесь привыкли совмещать теорию и практику. Пока ты не готов к практике и теоретизируешь, причём не имея понятия о предмете своих теорий, тебе здесь делать нечего.
Понятно, что для тебя - "сложная логика".

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

kokoc88

Открой мозг и включи глаза.
Да, в C# и Java тоже есть возможность получить Null pointer exception, как и в плюсах.
Чтобы этого не произошло в c#, надо аккуратно вести себя в конструкторах и деструкторах (впрочем, деструкторы, наверное, при наличии IDisposable нафиг не нужны).
Чтобы этого не произошло в плюсах, аккуратно надо себя вести везде. И думать ещё о куче других вещей.
Подтверди это примером кода на 5-10 строк? При чём меня интересуют следующие вопросы. Во-первых, почему файналайзеры (деструкторы) при наличии IDisposable нафиг не нужны? Во-вторых, почему в следующем коде, где я очень аккуратно веду себя в конструкторе, вылетает null pointer?
class CSharpClassWithVeryCarefulConstructor
{
public void func {}
}
...
static void someFunction
{
CSharpClassWithVeryCarefulConstructor c = null;
c.func;
}

kruzer25

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

kokoc88

Пример графа - могу. Просто влом, и непонятно, зачем.
Ну тогда приведи пример не графа, а чего-то другого и покороче. Но только такого, чтобы реализация на Си++ требовала того, на что ты изначально наехал: ручного вызова delete.

Dasar

да, основные подводные камни ты избежал.
к сожалению, в тех реальных приложениях, которые я встречал - все эти подводные камни избегались через раз и приводили к падениям.
да, в C# все было тоже самое - то бывает хороших код, который обходит подводные камни, бывает - плохой, но в C# это не приводило к падениям.
ps
но в твоем примере осталась еще одна проблема, что будет если один и тот же объект будет два раза добавлен в граф (второй раз неявно, как один из внуков самого себя)?

kokoc88

да, основные подводные камни ты избежал.

Кроме скорости работы. :smirk: (Ае, взял пенartoorчега2 на понт.) При реализации в лоб GC, конечно же, рулит подсчёт ссылок, если объекты очень маленькие. Это было не очевидно только для peenortoor2. (При увеличении размера объекта C# отжирает до 1гб и работает в десятки раз медленнее только из-за того, что свопится.) Завтра проведу дополнительные тесты. Пока что всех порвала Java :cool: , только ей нельзя ставить xmx больше 256mb. :crazy: Надеюсь, что они исправят эти странные проблемы с JVM. Кроме того, мне интересно проверить реализацию std:: tr1 ::shared_ptr от MS.
да, в C# все было тоже самое - то бывает хороших код, который обходит подводные камни, бывает - плохой, но в C# это не приводило к падениям.
У меня есть замечательный класс, который ипользуется уже в четвёртом коммерческом проекте. Он умеет сохранять дампы падения и намеренно ронять программу. Маст хэв для всех Си++ программ, жалко, что я не знаю, как убить .NET приложение с сохранением дампа. Помогло бы находить дедлоки.
но в твоем примере осталась еще одна проблема, что будет если один и тот же объект будет два раза добавлен в граф (второй раз неявно, как один из внуков самого себя)?

Граф строится на слабых ссылках, поэтому этой проблемы не возникает. Возникает другая проблема: нельзя начать граф от любой вершины, если ты удалил структуру хранения данных. Останется только эта вершина. Конечно, я мог бы решить и эту проблему с помощью смарт поинтеров, только в лом было. :)

Dasar

Маст хэв для всех Си++ программ, жалко, что я не знаю, как убить .NET приложение с сохранением дампа. Помогло бы находить дедлоки.
запускаешь windbg - и это он тебе по .net-у все без всякого убития выдаст.

kokoc88

запускаешь windbg - и это он тебе по .net-у все без всякого убития выдаст.
Ты его запускаешь у клиентов? Если локально, то и по Си++ тебе всё выдаст. Так мы можем сделать дампы, которые нам отсылают по инету.

williamsmith61

Охуенный тред, много интересного узнал. Ну и поржал конечно. Всем спасибо. :)
Надо заходить в раздел почаще...

kokoc88

Охуенный тред, много интересного узнал. Ну и поржал конечно. Всем спасибо.
Всегда пожалуйста.
Девелопмент вообще уникальный раздел: +- ставят от балды и без оснований, типа нефиг тут; кода мало пишут, чтобы не заклевали; ну и, естественно, заклёвывают тех, кто пытается запостить код. И ещё тут водятся отборные ооебаны типа кохтпы и пенартоора, и психи типа меня.

FKTIF

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

kokoc88

а чо, в венде для этого уже нельзя без особых классов?
зы вчера на работе как раз скрипт накатал, который бектрейсы от корок шлёт на почту заинтересованным лицам.
Понимаешь, мы не катаем скрипты, чтобы отправить core клиентам. (Кстати, что вы делаете, если лимит на коре нулевой?) Мы устанавливаем программу методом "one click", и она потом автономно работает.
И вообще вместо того, чтобы начинать холи вар, лучше бы пофиксил adept. Он всё время падает в кору. А автор, видимо школьник, кто ещё будет программировать забесплатно, не фиксит в нём баги. Хотя я честно отправлял кору раз десять, наверное.

FKTIF

хмык, прицеплять к кронтабу дополнительную строчку - ладно, с проверкой, может она уже есть - это типа пиздец сложно? Делается автоматически - это же юнипс. Ну и задача отправки бектрейса сложнее задачи отправки корки, если уж на то пошло ;)
(Кстати, что вы делаете, если лимит на коре нулевой?)
мы пишем для себя, поэтому не нулевой, приложения 365/7/24 валящиеся раз в сутки, и нас не ебут проблемы пионеров с вендой и next-next-next - нам бы со своими разобраться :D
 
И вообще вместо того, чтобы начинать холи вар, лучше бы пофиксил adept.

начнём другой и продолжим старый: кде говно, потому что написано на C++

kokoc88

начнём другой и продолжим старый: кде говно, потому что написано на C++
Так у тебя проблемы с Си++ или с вендой?

FKTIF

на венду мне посрать: сама сдохнет. У меня проблемы именно с цепепе. Я даже скажу почему - у него нет нормальной стандартной библиотеки. Чтобы строчку по-человечески поделить на разделителях, нужно свою хуйню бабахать. То, что есть в бусте - полное говно и плод воображения любителя грибов. А оставшиеся сторонние библиотеки - тоже говно (копирайт ты).

kokoc88

Чтобы строчку по-человечески поделить на разделителях, нужно свою хуйню бабахать. То, что есть в бусте - полное говно и плод воображения любителя грибов.
Да, в бусте не всё удобно.
Что касается библиотеки, то в Си++ нету так же SMTP (есть в .NET сокетов (.NET, Java POP3 (почему-то нету в .NET!?) и много чего ещё. Дело в том, что C# тесно связан с платформой .NET, а Си++ это скорее язык програмирования. Если ты заметил, то мы здесь не обсуждаем RAD или приверженцев одного языка программирования, или платформы для разработки ПО. Кстати, на C# я сделал больше коммерческих проектов, чем на Си++.
PS А венда не сдохнет. :cool:

kokoc88

Чтобы строчку по-человечески поделить на разделителях, нужно свою хуйню бабахать.
Ну это всё-таки необязательно.
	std::vector<std::string> tokens;
std::string source("blabla,blablabla,zomg,v rot mne nogi,v glaz pechen'e");
boost::split(tokens, source, boost::is_any_of(",";

margadon

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