LINUX.ORG.RU

C != C++


0

0

http://david.tribble.com/text/cdiffs.htm

Сравнение Си и Цпп. Примечательно, что Си содержит массу фич, не поддерживаемых C++, например

C99 supports variable-length arrays, which are arrays of automatic storage whose size is determined dynamically at program execution time. For example:

size_t sum(int sz)
{
float arr[sz]; // VLA, dynamically allocated

while (sz-- > 0)
arr[sz] = sz;
return sizeof(arr); // Evaluated at runtime
}

C++ does not support VLAs.

Надеюсь красноглазые фанаты уяснят наконец, что это разные языки. С++ - не улучшеный Си.

★★

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

>man ADT, затем поботай на тему грамотной реализации ADT на С. Какая, нахрен, "насквозь открытая структура".

Я тут пол-часа назад исследовал вопрос «Трудно ли зарегестрироваться на ЛОРе?» Оказалось, что нет. Логично предположить, что анонимус — это не «незарегистрированный пользователь», а специально разлогинившийся обитатель форума. Скажите, вы это делаете, чтобы не нести ответственность за свои слова? Залогинтесь, и я (быть может) расскажу про грамотную реализацию абстрактных типов данных на Си (и отличие от таковой в C++). И про публичность полей в struct тоже могу рассказать.

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

>я (быть может) расскажу про грамотную реализацию абстрактных типов данных на Си

Поздняк метаться и лепить гнилые отмазки, раз уж так лажанулся. "Инкапсуляция: обычные struct'ы, насквозь открытые — они «скрывают» состояние классов." Гы. Расскажешь про грамотную реализацию. Три раза гы.

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

Приведите, будьте добры, название книжки Розенталя.

>к которому принуждает практика программирования на C++.

Это тоже наглая ложь. (Вы уж извините, если вам такие заявы кажутся черезчур резкими. Да, я мог бы скруглить углы в духе «это не совсем верно», но таки хочу акцентировать.) C++ ни к чему не принуждает, это мультипарадигменный язык. Например, сортировка — это и в C++ функция, а не «сортирующий класс». И два листа процедурного стиля на C++ потребуют не больше места и усилий, чем то же самое на Си. А в объектно-ориентированном стиле — гарантированно меньше.

>то, в контексте чего проходит полемика, т.е. язык C++, и нечто, уровнем выше.

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

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

>Часто в качестве непрозрачного дескриптора (opaque handle) выступает указатель на структуру (содержимое которой недоступно, т.е. видно только объявление а-ля struct foo). Это является механизмом инкапсуляции, по мощности совершенно идентичным C++ pimpl idiom.

Про идиому Pimpl я в курсе. Что такое надёжно инкапсулированные данные? Это данные, которые а) недоступны, б) невидимы. Объявление полей класса private в C++ позволяет добится выполнения условия а). Pimpl позволяет добиться условия б).

Далее, в C++ только условия а) зачастую достаточно. А В СИ ЭТОГО ДОБИТЬСЯ НЕВОЗМОЖНО! Pimpl, между прочим, стоит одного лишнего разыменования. А значит сишный код, сравнимый по безопасности с плюсовым, будет (внимание!) медленнее! Из-за этого самого Pimpl, о котором вы рассказываете, как о «грамотной реализации ADT».

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

> Приведите, будьте добры, название книжки Розенталя.

У меня "Справочник по правописанию и стилистике".

> Это тоже наглая ложь.

Я пропустил про мультипарадигменность С++, хочу акцентировать ваше внимание, что проект на C++, сложнее студенческого hello world на QButton, нуждается в тщательном проектировании опытным(и) специалистом(ами). Лисп, который мне так люб и дорого, в этом плане куда проще по всем понятным причинам (динамическая типизация, сборка мусора, абстракции высшего уровня и т.п.)

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

Честно говоря, не осилил, что тут пытались сказать. Если вы про реплику "ООП на Си", то "уровнем выше" - это не на Си. ООП на Си - широкая практика, от ядра до Гнома. Причём, в гномовые библиотеки лазить не менее страшно, чем в плюсатые.

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

>Pimpl позволяет добиться условия б).

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

>Pimpl, между прочим, стоит одного лишнего разыменования.

Говорить о Pimpl в C несколько некорректно (pimpl был упомянут как близкий аналог). Откуда там лишнее разыменование? Функция получает указатель непосредственно на структуру данных, с которой работает. Точно так же, как метод С++ получает неявный указатель this.

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

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

>Поздняк метаться и лепить гнилые отмазки, раз уж так лажанулся.

Что я, тупых троллей никогда не видел, чувак? «Лажанулся», хе-хе :)

Нет, я всё понимаю: ЛОР, своя специфика, культ анонимуса (или я ошибаюсь?) Просто у меня к анонимусам несколько предвзятое отношение. Чтоб их отличать, я дам этому погонялово ГнилыеОтмазки.

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

>дам этому погонялово ГнилыеОтмазки.

Я обижен. Всё, больше не буду играть с тобой в одной песочнице.

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

> Что такое надёжно инкапсулированные данные? Это данные, которые а) недоступны, б) невидимы.

> значит сишный код, сравнимый по безопасности с плюсовым, будет (внимание!) медленнее!

Объясните, плз, в каком месте код, приведенный ниже, менее защищен, чем плюсовый
или медленнее плюсового аналога (за исключением возможности inline, конечно).

===== START a.h =====
struct Data;

Data* createData( int value );
void addOne( Data* this );
int getValue( Data* this );
===== END a.h =====

===== START a.c =====
struct Data
{
  int value;
};

Data* createData( int value )
{
  Data* ret = (Data*)malloc( sizeof(Data) );
  ret->value = value;
  return ret;
}

void addOne( Data* this )
{
  this->value++;
}

int getValue( Data* this )
{
  return this->value;
}
===== END a.c =====

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

> Лисп, который мне так люб и дорого, в этом плане куда проще по всем понятным причинам (динамическая типизация, сборка мусора, абстракции высшего уровня и т.п.)

М-м-м... Я тоже люблю Лисп, но что-то мне подсказывает, что проект, аналогичный 100000 SLOC на C++ без проектирования тоже не ахти какой замечательный получится. Даже наоборот -- без нормально построенного процесса разработки с тестированием и т.п., все глюки будут всплывать в рантайме.

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

> М-м-м... Я тоже люблю Лисп, но что-то мне подсказывает, что проект, аналогичный 100000 SLOC на C++ без проектирования тоже не ахти какой замечательный получится.

Только клепать проще и быстрее. А плохую плюсатую программу на 100к строк ещё нужно постараться спроектировать! ;)

> Даже наоборот -- без нормально построенного процесса разработки с тестированием и т.п., все глюки будут всплывать в рантайме.

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

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

А простые вещи на Лиспе так вообще очень быстро делать: тяп-ляп, поехали :)

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

>ты должен знать, что pimpl используется не только и не столько для сокрытия данных.

Хм... Сокрытие деталей реализации с целью уменьшения зависимостей времени компиляции, что тут непонятного-то? При изменении реализации класса не требуются перекомпиляция тех единиц трансляции, которые этот класс испольуют. Это всё отлично прописано у Скотта М., Герба. С. и Андрея А.

>Начинаю сильно сомневаться, что ты понимаешь, о чём идёт речь.

Я понимаю, о чём идёт речь.

>Точно так же, как метод С++ получает неявный указатель this.

Нет, немного не так. Указатель на this и указатель на impl — это разные вещи. Смотри, рано или поздно, пользователь твоей библиотеки должен будет создать экземпляр класса (в случае Си — структуры). А затем передавать её дрес в функции-«члены». Так вот, если этого лишнего уровня косвенности не будет, то при изменении *твоей* библиотеки, пользователю придётся перекомпилировать *свой* код. В C++, где класс реализован с использованием Pimpl — нет. Из-за этого самого лишнего уровня косвенности. Выигрываем во времени компиляции, проигрываем во времени исполнения.

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

> Выигрываем во времени компиляции, проигрываем во времени исполнения.

Читаемость кода, использующего pimpl, тоже страдает. Было: member, стало: impl->member.

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

>У меня "Справочник по правописанию и стилистике".

А у меня есть Страуструп, TC++PL3. На странице 57 он пишет: «C++... лучше, чем C». Я понимаю, у всех свои авторитеты. У кого-то Розенталь, у кого-то Луговский, а я вот и Страутсрупом не гнушаюсь.

>Я пропустил про мультипарадигменность С++, хочу акцентировать ваше внимание, что проект на C++, сложнее студенческого hello world на QButton, нуждается в тщательном проектировании опытным(и) специалистом(ами).

Ещё раз: всё что написано на Си может быть единообразно написано на C++. Наоборот — нет, приётся использовать костыли вроде ООП-для-бедных. Если проект на C++ сложнен, и нуждается в тщательном проетировании, то на Си и подавно.

>Лисп, который мне так люб и дорого, в этом плане куда проще...

Да, Лисп хороший язык. Я в нём не шибко разбираюсь, при беглом знакомстве он мне вполне понравился, буду осваивать.

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

>Я понимаю, о чём идёт речь.

Речь шла в точности о том методе, который выше продемонстрировал watashiwa_daredeska. Единственный проигрыш по сравнению с классом в самом хедере -- невозможность самому выделить память под структуру (на стеке, в частности). Ну так на то оно и ADT.

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

>Читаемость кода, использующего pimpl, тоже страдает. Было: member, стало: impl->member.

Согласен, но в Си это приходится делать ПОВСЕМЕСТНО, в функциях-«членах». А в C++ нет, если только тебе специально не требуется Pimpl.

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

> А у меня есть Страуструп, TC++PL3. На странице 57 он пишет: «C++... лучше, чем C».

Страуструп помагает вам лучше понимать сложносочинённые и сложноподчинённые предложения?

ps: У меня этот талмуд тоже есть.

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

> Согласен, но в Си это приходится делать ПОВСЕМЕСТНО, в функциях-«членах». А в C++ нет, если только тебе специально не требуется Pimpl.

Объектный код на Си - это полный пэ. Слёзно смотрел на недописанные плюсатые биндинги к gstreamer'у, скрежеща зубами писал свои баяны, с надеждой смотрю, что там у Vala получится.

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

Пожалуй, это лучший способ имитации инкапсуляции на Си. Но!

>Объясните, плз, в каком месте код, приведенный ниже, менее защищен, чем плюсовый или медленнее плюсового аналога (за исключением возможности inline, конечно).

Функция возвращает указатель на выделенную память. В некоторых конторах за такое могут уволить. Уж лучше возвращать указатель одним из параметров, чтоб возвращаемое значение нельзя было пригнорировать. Но дело даже не в этом.

В C++ есть могучая штука RAII. Точнее даже на сама аббревиатура RAII, а тот факт, что в C++ есть автоматический вызов дторов при свёртке стека. Это позволяет гарантировать, что некоторое действие (чаще всего возврат ресурсов) будет выполнено при выходе из скоупа независимо от а) исключений (для Си не так актуально), б) control flow graf'а (return в глубокой ветке if), в) забывчивости программиста. Даже самый глупый smart pointer не реализуем средствами Си.

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

>Речь шла в точности о том методе, который выше продемонстрировал watashiwa_daredeska.

Ответил выше. Если кратко и мелко: слабая защищённость от утечек памяти.

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

> Функция возвращает указатель на выделенную память.

> тот факт, что в C++ есть автоматический вызов дторов при свёртке стека.

У более других языков есть автоматические сборщики мусора, до которых C++ пока не дорос. И что теперь? Это фичи языков разного уровня. C -- для более низкоуровневого программирования, позволяет делать вещи, которые могут потенциально вылезти боком, высокоуровневые языки защищают от многой рутины и источников ошибок -- освобождение памяти, указатели и пр. А что дает C++? Возможность получить сегфолт на dumb pointer'е + тормоза на smart pointer'ах посильнее некоторых GC + тормоза от exception'ов и RTTI?

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

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

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

>C -- для более низкоуровневого программирования, позволяет делать вещи, которые могут потенциально вылезти боком...

На C++ можно спуститься сколь угодно низко к Си.

>А что дает C++? Возможность получить сегфолт на dumb pointer'е + тормоза на smart pointer'ах посильнее некоторых GC + тормоза от exception'ов и RTTI?

Вот вроде бы предыдущий комментарий от вас вполне по делу был, а сейчас эмоции одни. Ежели вменяемых комментариев нет, никто в обиде не останется, и подначивать угрозами «защитывания слива» не в моих привычках. Уж лучше без комментариев, чем с такими. Неинтересно, право слово.

>Возможность получить сегфолт на dumb pointer'е

Это в контексте сравнения с Си???

>тормоза на smart pointer'ах посильнее некоторых GC

А вы меряли? Чтобы избежать указанной проблемы вашего предыдущего примера, в C++ хватило бы самого слабого из умных указателей — boost::scope_ptr<> (это почти как std::auto_ptr<>, только noncopyable). Какие там тормоза, там даже счётчика ссылок нет!

>тормоза от exception'ов и RTTI

И то, и другое можно отключить в настройках компилятора (у меня MSVC 8.0). Но эти якобы «тормоза» позволяют писать гораздо более безопасный код.

>C -- для более низкоуровневого программирования...

Вот это меня и беспокоит. Почему же тогда берутся делать огромные проекты (требующие более высоких уровней абстракции, чем те, которые предлагает Си) на Си? Скажем, для GCC понятно, у них туева хуча legacy кода. Но откуда берутся фрики, активно продвигающие Си как повсеместную альтернативу C++ — не представляю.

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

>А ещё высокоуровневые языки позволяют вызывать функции из сишных библиотек, что практический смысл существования C++ сводит на нет.

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

>практический смысл существования C++ сводит на нет.

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

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

>У более других языков есть автоматические сборщики мусора, до которых C++ пока не дорос.

Из «доросших» языков могу порекомендовать <a href="http://www.digitalmars.com/d/index.html">D</a>;.

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

> А вы меряли?

Этот тест в основном на работу с памятью:
http://shootout.alioth.debian.org/gp4/benchmark.php?test=binarytrees&lang...

Причем, заметьте, в C++ не используются smart pointer'ы, которые еще ухудшат положение.

> Чтобы избежать указанной проблемы вашего предыдущего примера, в C++ хватило бы самого слабого из умных указателей — boost::scope_ptr<>

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

Однако, это все не про то. Да, в C++ есть smart pointer'ы, но их куча, что создает некоторую кашу и необходимость отвлекаться на выбор нужного. В истинно высокоуровневых языках мне не надо забивать голову этими пустяками. Как показывает тест выше, современные GC неплохо справляются с задачей управления памятью, а мне найдется чем голову занять.

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

> И то, и другое можно отключить в настройках компилятора (у меня MSVC 8.0). Но эти якобы «тормоза» позволяют писать гораздо более безопасный код.

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

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

> Т. е. мы уже пришли к выводу, что объективно обусловленных причин предпочесть Си нет?

А я Си, заметьте, нигде и не продвигал.

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

> Ну вы же сами сказали, что объектный код на Си выглядит ужасно?

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

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

> Почему же тогда берутся делать огромные проекты (требующие более высоких уровней абстракции, чем те, которые предлагает Си) на Си?

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

Ну и, опять же, reusability (если вести речь о библиотеках). C-интерфейс достаточно универсален. Его можно относительно легко забиндить куда угодно, чего не скажешь о C++.

> Но откуда берутся фрики, активно продвигающие Си как повсеместную альтернативу C++ — не представляю.

Ну, скажем так, единственной замены для C++ нет. Однако, положа руку на сердце, областей, где действительно стоит использовать C++, весьма и весьма немного и то, за счет того, что самую тяжелую и грязную работу кто-то уже сделал и завернул в библиотку.

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

> Однако, это все не про то. Да, в C++ есть smart pointer'ы, но их куча, что создает некоторую кашу и необходимость отвлекаться на выбор нужного.

справедливости ради все-таки стоит отметить, что в языке C++ нет умных указателей как классе - это парадигма библиотеки, в STL есть всего один - std::auto_ptr<> so проблемы выбора вроде не стоит, в boost их по большому счету 4 (scoped_ptr/array + shared_ptr/array). впрочем, если человек взялся использовать boost [любую его часть, хоть самую малую] предполагается, что он достаточно хорошо владеет языком so проблемы что выбрать - scoped или shared - у него то-же стоять не может.

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

по ссылке не ходил [завтра] но вопрос - указанный GC естественно thread safe? когда в одном потоке можно создать boost::shared_ptr<foo>, поместить допустим в контейнер а в других безопасно использовать.

// wbr

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

> по ссылке не ходил [завтра] но вопрос - указанный GC естественно thread safe? когда в одном потоке можно создать boost::shared_ptr<foo>, поместить допустим в контейнер а в других безопасно использовать.

впрочем, сходил. если честно, не совсем понял, причём же тут GC :-/

// wbr

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

> проблемы что выбрать - scoped или shared - у него то-же стоять не может.

Тут такая психология идет... Проблем вроде бы нет, все понятно, легко и привычно. Но, попробовав пописать на высокоуровневом языке, замечаю, что гораздо больше думаю о сути проблемы, а не о выборе smart/scoped/auto_ptr, о способах объехать покрасивше map/filter или for, о всяких мелочах, вроде того, как бы попроще записать жонглирование итераторами STL и пр.

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

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

>проблемы что выбрать - scoped или shared - у него то-же стоять не может.

Есть такая хрень в бусте -- weak_ptr. Циклическиме ссылки, для shared_ptr, проблема неразрешимая, пришлось родить костыль. Одно только избавление от необходимости использовать это чудо -- уже повод уйти на язык с GC.

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

> если честно, не совсем понял, причём же тут GC :-/

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

В подобного рода тестах, расхождение до 2-х раз можно считать несущественным, поэтому равными с C++ можно считать всех вплоть до C#(Mono) включительно. Из них подавляющее большинство использует GC. Про всех не знаю, однако у SBCL и Erlang, как минимум, с многопоточностью все в порядке, чего нельзя сказать об auto/shared_ptr в C++. Кое чего можно добиться intrusive_ptr'ом, но это требует дополнительной работы, не относящейся к делу, и скорее всего, будет в разы проигрывать GC ввиду интенсивных блокировок на подсчете ссылок.

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

> Тут такая психология идет... Проблем вроде бы нет, все понятно, легко и привычно. Но, попробовав пописать на высокоуровневом языке, замечаю, что гораздо больше думаю о сути проблемы, а не о выборе smart/scoped/auto_ptr, о способах объехать покрасивше map/filter или for, о всяких мелочах, вроде того, как бы попроще записать жонглирование итераторами STL и пр.

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

допустим, краем глаза посмотрев на Erlang осталось двойственное ощущение. с одной стороны, инструмент несомненно интересный. охотно верю, что используя его можно делать мощные вещи. с другой, для того, чтобы его реально использовать в каком-то боевом проекте*, придётся потратить массу времени изучение. это и язык, и окружение, и библиотеки, и best practice и так далее и тому подобное. как минимум это достаточно долго и не так просто. нужно ли оно? оправдаются ли затраты? и масса аналогичных вопросов..

*) AFAIU ejabberd написан на Erlang-е. это как первый попавшийся в голову пример "боевого проекта". нет, я ни разу его не смотрел и даже не скачивал, но если делать оценку по аналогам - например с jabberd2 - то проект не самый простой зато похож на то, чем приходится заниматься в том числе.

// wbr

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

> у первого есть давно наработанные и проверенные схемы которые он в дальнейшем использует. у второго их нет so приходится исследовать все на ходу.

Я не говорю об исследовании или каких-то осознанных размышлениях над выбором. Мне тяжело это описать, т.к. по ощущениям вроде все smoothly, но... Во, подобрал аналог -- разговор по телефону, что может быть проще? Однако, разговор по телефону за рулем примерно эквивалентен выпитой бутылке пива (или двум? т.к. по каким-то другим исследованиям, ~бутылка пива улучшает реакцию :) ).

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

>Выкиньте наследство Си - и получите отличный язык, который, к слову, называется D.

Ты кто?

При создании Ди ставилась задача максимальной совместимости с Си (которая стала даже выше, чем была у С++), и избавления от гадких слизкостей цпп. Он даже не линкуется с ним, ибо "The C++ runtime object model is just too complicated - properly supporting it would essentially imply making D a full C++ compiler too." Покажи мне хоть одну конструкцию Си, не работающую в Ди, кроме препроцессора?

Даже после добавления в язык некоторых высокоуровнивостей, он стал с виду больше похож на Си, чем С++ (я имею в виду не назначения ключевых слов, а общий вид кода, который, в случае D, напоминает кристально чистый, гладкий и понятный Си с его привычными языковыми конструкциями и принципами, нежели спагетти из всяких кренделей, шаблонов, boost'ов и прочего нечитабельного дерьма С++).

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

> Про всех не знаю, однако у SBCL и Erlang, как минимум, с многопоточностью все в порядке, чего нельзя сказать об auto/shared_ptr в C++.

btw если не секрет, какие проблемы у boost::shared_ptr с многопоточностью?

Thread Safety

--- boost docs ---
Thread Safety

shared_ptr objects offer the same level of thread safety as built-in types. A shared_ptr instance can be "read" (accessed using only const operations) simultaneously by multiple threads. Different shared_ptr instances can be "written to" (accessed using mutable operations such as operator= or reset) simultaneosly by multiple threads (even when these instances are copies, and share the same reference count underneath.)

Any other simultaneous accesses result in undefined behavior.

Examples:

shared_ptr<int> p(new int(42));

//--- Example 1 ---

// thread A
shared_ptr<int> p2(p); // reads p

// thread B
shared_ptr<int> p3(p); // OK, multiple reads are safe

//--- Example 2 ---

// thread A
p.reset(new int(1912)); // writes p

// thread B
p2.reset(); // OK, writes p2

//--- Example 3 ---

// thread A
p = p3; // reads p3, writes p

// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write

//--- Example 4 ---

// thread A
p3 = p2; // reads p2, writes p3

// thread B
// p2 goes out of scope: undefined, the destructor is considered a "write access"

//--- Example 5 ---

// thread A
p3.reset(new int(1));

// thread B
p3.reset(new int(2)); // undefined, multiple writes

--- boost docs ---

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

ну например, кеш каких-то динамических объектов. std::map<key, boost::shared_ptr<foo> >. доступ к самому map-у естественно защищён отдельным мьютексом. цель состоит в том, чтобы получив после поиска по кешу обернутый указатель на объект работать с ним сколько влезет не беспокоясь если кто-то вдруг решит в это время удалить объект из кеша. по крайней мере, это пример вполне работает.

ps: у std::auto_ptr по понятным причинам проблем с многопоточностью нет в принципе как класса.

// wbr

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

> btw если не секрет, какие проблемы у boost::shared_ptr с многопоточностью?

Да, неправильно в свое время понял документацию при чтении по диагонали :) Каюсь.

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

Кстати, ради спортивного интереса взял тот тест с шутаута, заменил все указатели на boost::shared_ptr<Node> и убрал все delete.

Для моей машины:
Оригинальный тест: 3.7+-0.1с
Тест с shared_ptr: 15.5+-0.1с

Разница в 4 раза, однако. Память не мерял, но shared_ptr делает лишнее выделение на каждый счетчик, по идее. Хотя, может оптимизирует как-то, не проверял.

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

> у std::auto_ptr по понятным причинам проблем с многопоточностью нет в принципе как класса.

Потенциально есть. Пусть auto_ptr<int> x является owner'ом объекта, тогда:

Thread A:
auto_ptr<int> y(x);

Thread B:
auto_ptr<int> z(x);

Потенциально, возможна ситуация, когда и y, и z получат ownership.

<5minutes skipped>

Глянул в исходники. Все вертится вокруг метода release:

element_type*
release() throw()
{
  element_type* __tmp = _M_ptr;
  _M_ptr = 0;
  return __tmp;
}

потоконебезопасность очевидна, по-моему.

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

>> у std::auto_ptr по понятным причинам проблем с многопоточностью нет в принципе как класса.
> Потенциально есть. Пусть auto_ptr<int> x является owner'ом объекта, тогда:

хм. я имел ввиду, что std::auto_ptr by design потоконезащищенный и использовать его без дополнительных средств синхронизации мягко говоря неразумно.

// wbr

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

> я имел ввиду, что std::auto_ptr by design потоконезащищенный и использовать его без дополнительных средств синхронизации мягко говоря неразумно.

Это не называется "отсутствие проблем". Это называется "положили болт". В результате, программист должен отслеживать (пусть и на "рефлекторном" уровне) еще и потокобезопасность, реализуя ее, возможно, самостоятельно.

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

> Ну насмешил... Ты хоть раз пользовался этим глючным чудовищем?

Конечно!

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

> Это не называется "отсутствие проблем". Это называется "положили болт". В результате, программист должен отслеживать (пусть и на "рефлекторном" уровне) еще и потокобезопасность, реализуя ее, возможно, самостоятельно.

ну [пока?] в стандарте C++ в принципе нет ничего, что как-то могло бы касаться распараллеливания и потоков в том числе. так что это общий подход.

// wbr

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

>ну [пока?] в стандарте C++ в принципе нет ничего, что как-то могло бы касаться распараллеливания и потоков в том числе. так что это общий подход.

ЕМНИП в 0х какую-то поддержку потоков сделают. В отличии от GC.

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

> так что это общий подход.

Для стандартного C++ -- да, именно руководствуясь им я неправильно понял документацию по shared_ptr. Однако, насколько я знаю, в 0x включат shared_ptr'ы. Внимание, вопрос: останутся ли shared_ptr по прежнему потокобезопасны, а auto_ptr по прежнему потоконебезопасны?

К слову, такого мелкого барахла с совместимостью в C++ накопилось уже порядком. Например, пресловутые "for( int i=0; ...". Помнится, в середине 90-х i принадлежала внешнему контексту, теперь -- внутреннему. Плохо то, что нельзя изменить поведение локально для, скажем, legacy-кода. Это означает, что при написании программы на C++ никогда не знаешь, что отвалится лет через 10, когда выйдет очередной стандарт.

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

>Это означает, что при написании программы на C++ никогда не знаешь, что отвалится лет через 10, когда выйдет очередной стандарт.

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

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