Что делает C ++ лучше, чем D?

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

Мне нравится D. Это приятный язык, который каким-то образом, огромным обновлением до C и прекрасно выполнен. Ни одна из функций не кажется «запертой», но на самом деле достаточно продуманной и хорошо продуманной.

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

Сам, пока я знаю C, я не могу сказать, что знаю C ++. Я хотел бы услышать от кого-то, кто знает как C ++, так и D, если они думают, что C ++ лучше, чем D как язык (что означает не обычное «у него больше сторонних библиотек» или « есть больше ресурсов "или" больше заданий, требующих C ++, чем D существует ").

D был разработан некоторыми очень опытными программистами на С ++ ( Уолтер Брайт и Andrei Alexandrescu , с помощью сообщества D), чтобы исправить многие проблемы, которые имел C ++, но было ли что-то, что на самом деле не улучшилось? Что-то он пропустил? Что-то, что вы считаете не лучшим решением?

Также обратите внимание, что я говорю о D 2.0 , а не D 1.0 .

135 голосов | спросил Anto 30 J000000Saturday11 2011, 12:23:09

8 ответов


124

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

Что касается самого языка, есть несколько вещей, которые C ++ лучше, чем D, на мой взгляд. Там, вероятно, больше, но вот несколько, которые я могу перечислить с головы:

C ++ имеет более продуманную систему типов
На данный момент существует довольно много проблем с системой типов в D, которые, как представляется, являются провалами в дизайне. Например, в настоящее время невозможно скопировать const-структуру в структуру non-const, если структура содержит ссылки на объекты класса или указатели из-за транзитивности const и способ использования конструкторов postblit для типов значений. Андрей говорит, что знает, как это решить, но не дал никаких подробностей. Проблема, безусловно, исправлена ​​(введение конструкторов копирования в стиле C ++ было бы одним исправлением), но в настоящее время это серьезная проблема в языке.

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

Наконец, учитывая эти существующие проблемы, я беспокоюсь о том, как остальные системы типов (pure, shared и т. д.) будут взаимодействовать со всем остальным в язык после их использования. В настоящее время стандартная библиотека (Phobos) очень мало использует систему D-типа с расширенным типом, поэтому я думаю, что разумно задаться вопросом, будет ли она задерживаться под напряжением. Я настроен скептически, но оптимистичен.

Обратите внимание, что C ++ имеет некоторые системные бородавки (например, non-transitive const, требующие iterator, а также const_iterator), которые делают его довольно уродливым, но в то время как система типа C ++ немного ошибается в деталях, это не мешает вам выполнять работу, как это иногда бывает D.

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

D иногда слишком удобен
Одна критика, которую вы часто слышите о C ++, заключается в том, что она скрывает некоторые проблемы низкого уровня от вас, например. простые присваивания, такие как a = b;, могут выполнять многие вещи, такие как вызов операторов преобразования, вызов операторов перегрузки и т. д., которые могут быть трудно увидеть из кода. Некоторым людям это нравится, некоторые люди этого не делают. В любом случае, в D это хуже (лучше?) Из-за таких вещей, как opDispatch, @property, opApply, lazy code>, которые могут изменить невинный код в то, чего вы не ожидаете.

Я не думаю, что это большая проблема лично, но некоторые могут найти это отключение.

D требуется сбор мусора
Это можно рассматривать как противоречивое, поскольку можно запустить D без GC. Однако только потому, что это возможно, это не значит, что это практично. Без GC вы потеряете много функций D, и использование стандартной библиотеки будет похоже на прогулку на минном поле (кто знает, какие функции выделяют память?). Лично я считаю совершенно нецелесообразным использовать D без GC, и если вы не являетесь поклонником GC (например, я), тогда это может быть совершенно неэффективным.

Наивные определения массива в D выделяют память
Это мое домашнее животное:

int[3] a = [1, 2, 3]; // in D, this allocates then copies
int a[3] = {1, 2, 3}; // in C++, this doesn't allocate

По-видимому, чтобы избежать выделения в D, выдолжен:

static const int[3] staticA = [1, 2, 3]; // in data segment
int[3] a = staticA; // non-allocating copy

Эти небольшие «за спиной» распределения - хорошие примеры моих предыдущих двух пунктов.

Изменить: обратите внимание, что это известная проблема, над которой работает.
Изменить: теперь это исправлено. Распределение не происходит.

Заключение
Я сосредоточился на негативах D против C ++, потому что это то, о чем задавался вопрос, но, пожалуйста, не см. Этот пост как утверждение о том, что C ++ лучше, чем D. Я мог бы легко сделать более крупную запись мест, где D лучше, чем C ++. Это зависит от вас, чтобы принять решение о том, какой из них использовать.

ответил Peter Alexander 30 J000000Saturday11 2011, 16:18:06
132

Когда я присоединился к D development, я был в особом положении, будучи одним из тех, кто знает больше всего о C ++. Теперь я нахожусь в еще более своеобразной позиции, чтобы быть одним из тех, кто знает больше всего о том, что нужно знать о D. Я не говорю об этом с соответствующими правами или правами на хвастовство, а также замечаю, что я в курсе благоприятное положение для ответа на этот вопрос. То же самое относится к Уолтеру.

По большому счету, спрашивая, что C ++ (и под этим я подразумеваю C ++ 2011), лучше, чем D, является настолько противоречивым, как вопрос: «Если вы платите профессионалу, чтобы очистить свой дом, каковы места, где они «Я оставлю грязнее, чем раньше?» Независимо от того, что C ++ мог сделать то, что D не мог, он всегда стоял как больной палец для меня и Уолтера, поэтому почти по определению нет ничего, что мог бы сделать C ++, который не находится в пределах досягаемости D.

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

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

  1. D предполагает, что все объекты перемещаются побитовой копией. Это оставляет меньшинство проектов для C ++, особенно тех, которые используют внутренние указатели, т. Е. Класс, содержащий указатели внутри себя. (Любой такой проект можно перевести без каких-либо или незначительных затрат на эффективность в D, но при этом будет задействован перевод). Мы приняли это решение, чтобы значительно упростить язык, сделать копирование объектов более эффективным без вмешательства пользователя или минимального вмешательства и избегать все мошенничество в построении копии и ссылки на значения rvalue вообще.

  2. D запрещает типы двусмысленных гендерных типов (которые не могут решить, являются ли они значениями или ссылочными типами). Такие проекты единодушно избегают на C ++ и почти всегда ошибаются, но некоторые из них технически правильны. Мы сделали этот выбор, потому что он запрещает в основном неправильный код и только крошечный фрагмент кода, который можно перепроектировать. Мы считаем, что это хороший компромисс.

  3. D запрещает иерархии с несколькими корнями. Предыдущий плакат здесь очень волновался по поводу этой конкретной темы, но это хорошо проработанное основание, и нет никаких ощутимых преимуществ корневой иерархии по сравнению с иерархиями, которые имеют общий корень.

  4. В D вы не можете бросить, например. int. Вы должны бросить объект, наследующий Throwable. Нет никакого соревнования, состояние дел лучше в D, но, ну, это одно, что C ++ может сделать, что D не может.

  5. В C ++ единица инкапсуляции - это класс. В D это модуль (т. Е. Файл). Уолтер принял это решение по двум причинам: естественно сопоставить инкапсуляцию с семантикой защиты файловой системы и избавиться от необходимости «друга». Этот выбор очень хорошо сочетается с общей модульной конструкцией D. Можно было бы изменить вещи, чтобы быть больше похожими на C ++, но это могло бы заставить вещи; Выбор области инкапсуляции C ++ хорош только для физического дизайна C ++.

Может быть одна или две вещи меньшего размера, но в целом это должно быть.

ответил Andrei Alexandrescu 30 J000000Saturday11 2011, 18:40:36
65

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

На самом деле, я должен действительно разрушить мой мозг, чтобы придумать причины, по которым C ++, как язык, лучше, чем D. Что обычно приходит на ум, это вопрос компромиссов.

  1. Поскольку D's const является транзитивным и потому, что язык имеет неизменный , он имеет гораздо более сильные гарантии, чем C ++ const, что означает, что D не имеет и не может иметь mutable. Он не может логический const . Таким образом, вы получаете огромный выигрыш в системе D's const, но в некоторых ситуациях вы просто не можете использовать const, как это было бы на C ++.

  2. D имеет только один оператор-литье, тогда как C ++ имеет 4 (5, если вы считаете оператор C-трансляции). Это облегчает работу с бросками в D в общем случае, но является проблематичным, если вы действительно хотите дополнительные осложнения /преимущества, которые const_cast и его братья предоставляют. Но D на самом деле достаточно мощный, чтобы вы могли использовать шаблоны для внедрения C ++, поэтому, если вы действительно этого хотите, вы можете иметь их (и они могут даже оказаться в стандартной библиотеке D в какой-то момент).

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

  4. модульная система D намного чище, чем C ++'includes (не говоря уже, way быстрее при компиляции), но ему не хватает какого-либо пространства имен за пределами самих модулей. Итак, если вы хотите пространство имен внутри модуля, вам нужно пройти маршрут Java и использовать статические функции для класса или структуры. Он работает, но если вы действительно хотите пространство имен, это, очевидно, не так чисто, как реальное пространство имен. Однако для большинства ситуаций пространство имен, предоставляемое вами самими модулями, довольно много (и довольно сложное, когда дело касается таких вещей, как конфликты на самом деле).

  5. Подобно Java и C #, D имеет одинарное наследование, а не множественное наследование, но в отличие от Java и C #, это дает вам некоторые фантастические способы получить тот же эффект без всех проблем, с которыми сталкивается множественное наследование C ++ (и C ++ множественное наследование может иногда получать very беспорядочно). У D есть интерфейсы , но у него есть string mixins , шаблоны mixins , и alias this . Таким образом, конечный результат, возможно, более мощный и не имеет всех проблем, которые наследует множественное наследование C ++.

  6. Подобно C #, D выделяет structs и classes . Классы являются ссылочными типами, которые имеют наследование и выводятся из Object, тогда как структуры являются типами значений без наследования. Это разделение может быть хорошим и плохим. Он избавляется от классической проблемы среза на C ++ и помогает разделить типы, которые действительно являются типами значений из тех, которые должны быть полиморфными, но поначалу, по крайней мере, различие может быть раздражающим для программиста на С ++. В конечном счете, есть ряд преимуществ, но это заставляет вас иметь дело с вашими типами несколько иначе.

  7. функции classes по умолчанию являются полиморфными. Вы не можете объявить их не виртуальными . Это зависит от компилятора, чтобы решить, могут ли они быть (это действительно так, если они final и не перекрывают функцию из базового класса). Таким образом, это может быть проблемой производительности в некоторых случаях. Однако, если вам действительно не нужен полиморфизм, вам нужно всего лишь использовать structs , и это не проблема.

  8. D имеет встроенный сборщик мусора . Многие из C ++ считают, что это серьезный недостаток, и, правда, в настоящее время его реализация может использовать серьезную работу. Это улучшилось, но это определенно не совместимо с сборщиком мусора Java. Однако это смягчается двумя факторами. Один, если вы в основном используете структуры и другие типы данных в стеке , то это не большая проблема. Если ваша программа не постоянно выделяет и освобождает материал от кучи, все будет хорошо. И два, вы можете пропустить сборщик мусора , если хотите и просто используйте C malloc и free. Существуют некоторые языковые функции (например, сортировка массивов ), которые вы будете иметь чтобы избежать или быть осторожным, и некоторые из стандартной библиотеки не могут использоваться, по крайней мере, при использовании GC (в частности, строковая обработка), но вы можете писать в D, не используя сборщик мусора, если вы действительно этого хотите. Разумная вещь, которую нужно сделать, - это, вероятно, использовать ее вообще, а затем избегать ее, когда профилирование показывает, что это вызывает проблемы для критического кода производительности, но вы можете избежать этого полностью, если хотите. И качество реализации GC будет со временем улучшаться, устраняя многие о том, что использование GC может вызвать. Итак, в конечном итоге GC не будет такой большой проблемой, и в отличие от Java, вы можете избежать этого, если хотите.

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

И D, как язык, улучшает C ++ во многих отношениях, что я считаю, что в общем случае D объективно лучше.

  1. D имеет условную компиляцию . Это одна из особенностей, которые я часто пропускаю, когда программирую на C ++. Если C ++ добавит его, то C ++ будет улучшаться с помощью прыжков и ограничений, когда дело доходит до таких вещей, как шаблоны.

  2. D имеет отражение времени компиляции .

  3. Переменные по умолчанию являются потоковыми, но могут быть shared, если вы хотите, чтобы они были. Это делает работу с потоками far более чистым, чем на C ++. Вы в полном контроле. Вы можете использовать immutable и передачу сообщений для связи между потоками, или вы можете сделать переменные shared и сделать это с C ++ способом с мьютексами и переменными условия. Даже это улучшено по сравнению с C ++ с введением synchronized (аналогично C # и Ява). Таким образом, ситуация с потоками D far лучше, чем C ++.

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

  5. D имеет встроенный контрактное программирование .

  6. D имеет встроенную единичный тест .

  7. D имеет встроенную поддержку для Unicode с string (UTF-8), wstring (UTF-16) и dstring (UTF-32). Это упрощает работу с unicode. И если вы хотите просто использовать string и вообще не беспокоиться о unicode, вы можете - хотя некоторое понимание основ Unicode помогает с некоторыми стандартными библиотечными функциями.

  8. D's перегрузка оператора намного приятнее, чем C ++, что позволяет вы должны использовать одну функцию для одновременного перегрузки нескольких операторов. Ярким примером этого является необходимость перегрузитьбазовые арифметические операторы и их реализации идентичны, кроме оператора. String mixins делают его легким, позволяя вам иметь одно, простое определение функции для всех.

  9. массивы D намного лучше, чем массивы C ++. Они не только имеют правильный тип длины, но и могут быть добавлены и изменены. Конкатенировать их легко. И самое главное, они нарезка . И это мощный em для эффективной обработки массивов. Строки - это массивы символов в D, и это не проблема (на самом деле это здорово!), Потому что массивы D настолько сильны.

Я мог бы продолжать и продолжать. Многие улучшения, которые предоставляет D, - это небольшие вещи (например, использование this для имен конструкторов или запрещение операторов if или loop, где точка с запятой - все их тело), ​​но некоторые из них довольно большие, и когда вы добавляете все это вместе, это улучшает качество программирования much . C ++ 0x добавляет некоторые функции, которые D не имеет, что C ++ отсутствовал (например, auto и lambdas), но даже со всеми его улучшениями все еще не будет много, что объективно лучше о C ++ как языке, чем D.

Нет сомнений в том, что существует много субъективных причин, подобных друг другу, и относительная незрелость реализации D может быть проблемой иногда (хотя она очень быстро улучшалась в последнее время, тем более, что хранилища были перемещены github ), и отсутствие сторонних библиотек может определенно быть проблемой (хотя факт что D может легко вызвать функции C - и в меньшей степени Функции C ++ - определенно смягчает проблему). Но это качество вопросов реализации, а не проблемы с самим языком. И по мере того, как качество проблем реализации фиксировано, станет намного приятнее использовать D.

Итак, я полагаю, что короткий ответ на этот вопрос «очень мало». D, как язык, обычно превосходит C ++.

ответил Jonathan M Davis 30 J000000Saturday11 2011, 16:05:08
9

Использование памяти RAII и стека

D 2.0 не разрешает RAII в стеке, потому что он удаляет значение ключевого слова scope при распределении экземпляров класса в стеке.

Вы не можете выполнять наследование типа значения в D, так эффективно, что заставляет вас делать выделение кучи для любой формы RAII.
То есть, если вы не используете emplace, но это very больно использовать, поскольку вам нужно выделить память вручную. (Мне еще предстоит найти практическое использование emplace в D.)

ответил Mehrdad 3 SatEurope/Moscow2011-12-03T12:36:05+04:00Europe/Moscow12bEurope/MoscowSat, 03 Dec 2011 12:36:05 +0400 2011, 12:36:05
6

C ++ намного лучше заставляет вас быть многословным. Это может быть лучше или хуже в ваших глазах, в зависимости от того, нравится ли вам вывод или многословие.

Сравните меморандум во время выполнения на C ++ :

template <typename ReturnType, typename... Args>
function<ReturnType (Args...)> memoize(function<ReturnType (Args...)> func)
{
    map<tuple<Args...>, ReturnType> cache;
    return ([=](Args... args) mutable {
            tuple<Args...> t(args...);
            return cache.find(t) == cache.end()
                ? cache[t] : cache[t] = func(args...);
    });
}

с тем же самым в D:

auto memoize(F)(F func)
{
    alias ParameterTypeTuple!F Args;
    ReturnType!F[Tuple!Args] cache;
    return (Args args)
    {
        auto key = tuple(args);
        return key in cache ? cache[key] : (cache[key] = func(args));
    };
}

Обратите внимание, например, на дополнительную многословность с template <typename ReturnType, typename... Args> по сравнению с (F), Args... в сравнении с Args, args... против args и т. д.
К лучшему или худшему, C ++ более подробный.

Конечно, вы также можете сделать это в D:

template memoize(Return, Args...)
{
    Return delegate(Args) memoize(Return delegate(Args) func)
    {
        Return[Tuple!Args] cache;
        return delegate(Args args)
        {
            auto key = tuple(args);
            return key in cache ? cache[key] : (cache[key] = func(args));
        };
    }
}

, и они выглядели бы почти идентичными, но для этого потребовался бы делегат delegate, тогда как оригинальный принятый любой вызываемый объект. (Для версии C ++ 0x требуется объект std::function , поэтому в любом случае он более подробный и ограничительный в своих вводах ... что может быть хорошо, если вы как многословие, плохо, если вы этого не делаете.)

ответил Mehrdad 1 PM00000040000001731 2011, 16:26:17
2

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

Чтобы понять, почему D не получает больше тяги, вам нужно начать с понимания того, что привлекает людей к C ++. Одним словом, главной причиной является контроль. Когда вы программируете на C ++, у вас есть полный контроль над вашей программой. Хотите заменить стандартную библиотеку? Ты можешь. Хотите сделать небезопасные стрелки? Ты можешь. Хотите нарушить const-correctness? Ты можешь. Хотите заменить распределитель памяти? Ты можешь. Хотите скопировать необработанную память без учета ее типа? Если вы действительно этого захотите. Хотите наследовать от нескольких реализаций? Это ваши похороны. Черт, вы даже можете получить библиотеки сбора мусора, такие как сборщик Boehm. Тогда у вас есть проблемы, такие как производительность, которая внимательно следит за контролем - чем больше контроля у программиста, тем более оптимизированный он может сделать свою программу. Производительность является одной из основных причин продолжения использования C ++.

Вот несколько вещей, которые я видел, когда делал небольшое исследование и говорил с несколькими людьми, которые его пробовали:

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

Я слышал о проблемах с функциями и делегатами. По-видимому, D имеет обе функции и делегатов в качестве типов функций, вызываемых во время выполнения, и они не совпадают, но они взаимозаменяемы или ... что-то? У моего друга было немало проблем с ними. Это, безусловно, понижение от C ++, у которого просто есть std::function, и все готово.

Тогда у вас есть совместимость. D не особенно совместим с C ++. Я имею в виду, что язык no совместим с C ++, давайте посмотрим правде в глаза, кроме C ++ /CLI, который является своего рода обманом, но как барьер для входа, это нужно упомянуть.

Тогда есть и другие вещи. Например, просто прочитайте запись в Википедии.

import std.metastrings;
pragma(msg, Format!("7! = %s", fact_7));
pragma(msg, Format!("9! = %s", fact_9));

printf - одна из самых небезопасных функций, когда-либо созданных в том же семействе, что и большие проблемы, такие как gets из старой библиотеки C Standard. Если вы ищете его в Stack Overflow, вы найдете много и много вопросов, связанных с его неправильным использованием. По сути, printf является нарушением DRY - вы давая тип в строке формата, а затем давая его снова, когда вы даете ему аргумент. Нарушение DRY, где, если вы ошибаетесь, возникают очень плохие вещи, например, если вы изменили typedef от 16-битного целого до 32-битного. Он также не расширяется - представьте себе, что произойдет, если все придумают свои собственные спецификаторы формата. C ++ iostreams могут быть медленными, и их выбор оператора может быть не самым большим, и их интерфейс может использовать работу, но они в принципе гарантированно безопасны, а DRY не нарушаются, и их можно легко расширить. Это не то, что можно сказать о printf.

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

Другим примером является string и wstring. На C ++ уже довольно сложно конвертировать между ними, и эта библиотека поддерживает Unicode, и эта старая библиотека C использует только const char* и должна писать разные версии одной и той же функции в зависимости от тип аргумента строки, который вы хотите. Примечательно, что заголовки Windows, например, имеют некоторые чрезвычайно раздражающие макросы, чтобы справиться с проблемой, которая может часто мешать вашему собственному коду. Добавление dstring в микс только ухудшит ситуацию, так как теперь вместо двух типов строк вам нужно управлять тремя. Наличие нескольких типов строк приведет к увеличению болей в обслуживании и внедрению повторяющегося кода, связанного со строками.

Скотт Майерс пишет:

  

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

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

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

Кроме того, вы можете ожидать определенный рефлекс. D имеет сбор мусора, которые программисты на С ++ будут ассоциировать с такими языками, как Java и C #, которые прямо противоположны ему в философии, и синтаксические сходства также привнесут их в голову. Это не обязательно объективно оправдано, но это то, что, безусловно, следует отметить.

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

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

ответил Mehrdad 1 PM00000040000001731 2011, 16:26:17
1

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

D версия:

class A { int i; }

int foo(A a) {
    return a.i; // Will crash if a is null
}

int main() {
    A bar = null;
    // Do something, forgetting to set bar in all
    // branches until finally ending up at:
    return foo(bar);
}

Версия на C ++:

class A { int i; };

int foo(A& a) {
    return a.i; // Will probably not crash since
                // C++ references are less likely
                // to be null.
}

int main() {
    A* bar = null;
    // Do something, forgetting to set bar in all
    // branches until finally ending up at:
    // Hm.. I have to dereference the bar-pointer
    // here, otherwise it wont compile.  Lets add
    // a check for null before.
    if (bar)
        return foo(*bar);
    return 0;
}

Чтобы быть справедливым, вы можете приблизиться к C ++, сделав A в D struct и отметив foo() -argument как a ref (классы - это ссылочные типы, а struct - типы значений в D, аналогичные C #).

Я полагаю, что существует план создания шаблона NonNullable для классов как стандартная библиотека библиотеки D. Тем не менее, мне нравится краткость простого Type& по сравнению с NonNullable(Type) и предпочитает не-nullable как значение по умолчанию (отображение чего-то типа Type и Nullable(Type)). Но это слишком поздно, чтобы изменить это для D, и теперь я дрейфую вне темы.

ответил lumor 1 AM00000030000003231 2011, 03:44:32
1

Самое главное, что C ++ «лучше», чем D, взаимодействует с устаревшими библиотеками . Различные 3D-двигатели, OpenCL и так далее. Поскольку D является новым, у него гораздо меньше различных библиотек.

Другое важное различие между C ++ и D состоит в том, что C ++ имеет несколько независимых в финансовом отношении поставщиков, но с 2014 года D имеет практически только одну , созданную им 2-х парную команду. Интересно, что принцип «второго источника» , в котором говорится, что проекты никогда не должны зависеть от технологий, компонентов, которые имеют только один, один, поставщик, похоже, даже для программного обеспечения.

Для сравнения, первая версия интерпретатора Ruby была написана изобретателем Ruby, Yukihiro Matsumoto, но основной интерпретатор Ruby эпохи 2014 года был написан практически с нуля другими людьми. Таким образом, Ruby можно рассматривать как язык, на котором имеется более одного независимого финансового поставщика. D, с другой стороны, может быть отличной технологией, но это зависит от немногих разработчиков, которые ее разрабатывают.

История Java показывает, что даже если технология, в данном случае, у Java, имеет прекрасного, но единственного финансиста, существует большой риск того, что технология существенно сбрасывается независимо от огромной корпоративной базы пользователей. Ссылка на Apache Software Foundation , где ЕС обозначает «Исполнительный комитет»:

Oracle предоставила EC спецификационный запрос Java SE 7 и лицензию, которые противоречат друг другу, строго ограничивают распространение независимых реализаций спецификации, и, самое главное, запрещают распространение независимых версий с открытым исходным кодом спецификации.

Как историческое примечание, можно сказать, что Java-апплеты имели аппаратное ускорение 3D-холста за несколько лет до разработки HTML5 WebGL. Возможно, проблема с начальной загрузкой апплетов Java могла быть решена, если Java был проектом сообщества, но руководители единственного финансиста Java, Sun Microsystems, не нашли его достаточно важным для реализации Java-реализации. Конечный результат: холст HTML5 несколькими поставщиками как «реплика бедного человека» в инфраструктурах Java GUI (Swing и т. Д.). Интересно, что на стороне сервера язык программирования Python имеет те же преимущества, что и обещал Java: писать один раз, запускать на каждом сервере, независимо от оборудования, при условии, что приложение Python не скомпилировано для машинного кода. Python похож на старую /молодую, как Java, но в отличие от Java, она подкрепляется более чем одной независимой командой разработчиков (PyPy и интерпретатором основного потока Python).

Резюме:

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

Насколько выгодно использовать технологию T1 над технологией T2, зависит от поставщиков технологий и позволяет ли технология T1 решать проблемы, связанные с проектом, дешевле, чем T2. Например, если одна проблема поставщика была проигнорирована, то для информационных систем Java была бы «лучшей» технологией, чем C ++, потому что двоичные файлы Java не нуждаются в перекомпиляции при развертывании на новое оборудование и объеме работы по разработке программного обеспечения, связанного с управлением памятью для Java меньше, чем для C ++. Проекты, разработанные с нуля, например. проекты, которые не зависят от других библиотек, могут быть дешевле для разработки в D, чем C ++, но, с другой стороны, C ++ имеет более одного поставщика и поэтому менее рискован в долгосрочной перспективе. (Пример Java, где Sun Microsystems было почти нормально, но Oracle практически сделалJava «новый COBOL».)

Возможное обходное решение для некоторых ограничений C ++

Одним из возможных обходных путей для некоторых ограничений C ++ является использование шаблона проектирования, в котором начальная задача разбивается на части, а части сортируются (классифицируются, группируются, разделяются, другие-хорошие слова -for-the-same-thing) до 2-х классов: задачи управления логикой , где шаблоны доступа к памяти не позволяют локализовать; задачи обработки сигналов , где местность легко достигается. Задачи обработки сигналов «как» могут быть реализованы как набор относительно упрощенных консольных программ. Задачи, связанные с логикой управления, помещаются в один сценарий, написанный на Ruby или Python, или что-то в этом роде, где комфорт разработки программного обеспечения имеет более высокий приоритет, чем скорость.

Чтобы избежать дорогостоящей инициализации процесса операционной системы и копирования данных между процессами операционной системы, набор небольших консольных приложений C ++ может быть реализован как одна программа на C ++, которая загружается как «сервлет» с помощью Ruby /Python /etc. скрипт. Ruby /Python /etc. сценарий отключает сервлет перед выходом. Связь между «сервлетом» и Ruby /Python /и т. Д. скрипт выполняется по каналу с именем Linux или аналогичным механизмом.

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

ответил Martin Vahi 18 MaramTue, 18 Mar 2014 05:45:30 +04002014-03-18T05:45:30+04:0005 2014, 05:45:30

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132