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

C++


Чему учит нас C++, что он нам говорит, какие парадигмы он воздвигает?

1. Что можно именовать типы, методы и переменные маленькими буквами

        std::list<std::string> L;
	L.push_back(50);
	L.push_front(-50);

Вы спросите, что же плохого в именовании элементов маленькими буквами?

А то, что, во-первых, C++ не различает контекст типа и контекст переменной и функции! И вы не можете никак взять и объявить поле, скажем, size size или point point! Поэтому, имеет смысл именовать функции и переменные маленькими буквами, но только если тип именуется в стиле C#, а именование типа маленькими буквами портит весь смысл такого действия! А смысл заключается в невозможности пересечения имени типа и его членов!

Ну, а во-вторых, именование как C#, выглядит солиднее, красивее.

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

2. Что можно сокращать так, что будет непонятно тому, кто использует ваш код, но зато «быстро печатается». Или сокращать, но все же понятно.

Вот лишь некоторые методы из стандартной библиотеки:

	std::string s; s.rfind(); s.c_str();
	std::fstream fs; fs.copyfmt(); fs.rdbuf();

Вы что-нибудь поняли? Что есть «rfind» и почему не «find», что это за r такая? Что такое «c_str»? Нужно посмотреть документацию, чтобы понять, что это превращение строки в «строку как в С» — массив-указатель на символы…

3. Что можно использовать макросы, как универсальное средство решения проблем. При этом намеренно забывается, или умалчивается, что эти макросы можно легко заменить, и что они глобальны, не входят в какое-либо пространство имён.

Вот например:

	#define foreach(x,c) for(auto x = c.begin(); x != c.end(); x++)
	#define min(x,y) ((x)<(y) ? (x) : (y))
	#define true false
	#define NULL 1

Обратите также внимание на то, что если параметры параметризованного макроса не обставлять скобками, то все вычисления с этим макросом легко испортятся! А дело в том, что параметры раскрываемого макроса воспринимаются как текст (!), и если не поставить скобки, то мы получим примерно такие варианты:

	a = b * min(x,y);  //==>  a = b*x < y ? x : y;
	a = min(5,3*k)*100; //==>  a = 5 < 3*k ? 5 : 3*k*100;

Согласитесь, это не то, что мы ожидали! И только познавшие эту хитрость макросов с параметрами на своем горьком опыте, долгих мытарствах и восклицаниях: «боже, что я не так сделал!» (или прочитавшие документацию к языку), пишут такие макросы правильно (и то, нужно быть очень внимательным!).

4. Что вы сами, сами! ? должны делать многие вещи, которые в C++ поленились сделать.

  • Не реализована нормальная работа стека. Я до сих пор не понимаю, как он работает! А где взять привычный нам хеш (словарь/карту)?
  • Выделение памяти (new/malloc) жутко тормозит! Вы сами, сами! должны делать управлятель памятью (ничего себе задача!), либо довольствоваться медленной работой
  • Не реализованы элементарные классы — класс «Массив», класс «Двумерный массив» и класс «Трехмерный массив».
  • Не созданы преобразования базовых типов: строковых и числовых (в том числе и логических), их надо делать самому (хотя, есть для этого возможности)

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

5. Что можно свободно баловаться с указателями и даже с константными указателями, надо лишь правильно преобразовать типы. Взгляните:

	void Func(const int* x) {
		((int*)x)[0] = 5;
	}

	int main() {
		int m = 500;
		Func(&m);
		std::cout << m <<'\n';
		return 0;
	}

И что же выведется у нас? 5! Константный параметр изменил свое значение! Так можно любые константные указатели менять, даже строковые или числовые (правда их изменение влечет ошибку обращения с памятью). Или вот:

	struct T {
	int M,N;
	T(int m, int n) {
		M = m; N = n;
	}
	};

	int main() {
		static const T t = T{5,3};
		((T*)(&t))[0] = T(-1,-5);
		std::cout << t.M <<" "<< t.N << "\n";
		return 0;
	}

Здесь изменяется статическая константа структурного типа! То есть, та, в чьей неизменяемости мы уверены на все 100%! «А вот нет!» — говорит на C++. И выводится именно изменённое значение константы.

6. Что можно вываливать содержимое перечислений в общий контекст! При чем, без включения стандарта C++11, мы не сможем сделать иначе.

Это ужасно! Взгляните на это:

	enum Month {
		JANUARY,FEBRUARY,
		MARCH,APRIL,MAY,
		JUNE,JULY,AUGUST,
		SEPTEMBER,NOVEMBER, DECEMBER
	};
	...
	Month m = JANUARY;
	...
	switch(x) {
	case JANUARY:
	case FEBRUARY:
	}

А если элементы пересекаются — присутствуют и в одном, и в другом перечислении (например, такие вполне могущие повторяться «NORMAL», «DEFAULT»)? Что тогда?.. C++ попускает вызов перечислений именно таким образом! Ленивые распущенные программисты C++ скажут: «А что, также быстрее пишется, также можно!», им невдомёк, что это распущенность, как невдомёк тем, кто ходит на современные российские комедии («А что, это прикольно, как в жызни!»)!

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

Хотя, конечно, вы можете быть порядочным и именовать элементы перечисления правильно (как сами перечисления (здесь, вообще, врятли будет пересечение имени типа и его элемента, потому может быть одинаковый стиль, что предпочтительнее, т.к. красивее)) и не вываливать элементы в контекст, даже запрещая это добавлением слова «class» после ”enum" (стандарт C++11). Но не факт и здесь, что остальные будут такими же порядочными и соблюдать правила!

Правильно делать так:

	enum class Month {
		January, February,
		March,April,May,
		June,July,August,
		September,October,November, December
	};

7. Что вовсе не являются ошибкой такие вещи как:

  • не возврат функцией значения, или возврат не во всех условных ветках
  • использование не определенной переменной

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

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

	void F(int& x, int& y);
	. . .
	F(x,y);
	void FF(int x, int y);
	FF(x,y);

Что мы видим? Мы видим, что ЕСЛИ УБРАТЬ ЗНАК ССЫЛКА, ТО ВЫЗОВ НЕ ИЗМЕНИТСЯ. Мы можем не знать, где ссылочный параметр, где параметр-значение! Лишь по смыслу функции или при активации подсказки в IDE мы можем это определить!

Подведём итоги


С++ нам говорит: у меня нет некоторых важных вещей, ты должен достать или написать их сам, а еще в нашем «демократическом» языке нет четких правил, живите как хотите!

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

Меж тем, такие учения и парадигмы лишь портят прилежных программистов, к тому же, заставляя их создавать/искать некоторые базовые, необходимые, решения, плохо сказывась на мировоззрении и нервах программиста и ведущие к ухудшении удобочитаемости кода…

C#


Но взглянем на C#! Что же он нам говорит, какие парадигмы воздвигает, чему же учит?

1. Что слова в именах типов, функций, переменных начинаются с большой буквы и соединяются без разделителей (благодаря большим буквам слова видны). Это называется стилем C# (другое название ? стиль Pascal), представитель верблюжей группы стилей. Что первое слово имени каждой закрытой переменной начинается с маленькой, дабы не путать с открытыми ? стиль Java, второй представитель верблюжей группы стилей.

Контекст имен типов отличается от контекста имен функций, переменных и констант. Вы можете объявить поле Size Size или Point Point, и это скомпилируется и можно будет даже правильно использовать (даже сочетать имя поля и имя типа без использования this!)!

	struct Rect {
		Point Point;
		Size Size;
		// Функции...
		Rect(int x,int y,int w,int h) {
			Size = new Size(w,h);
			Point = new Point(x,y);
		}
		...
	}
	Rect r = new Rect(new Point(5,5), new Size(300,200));

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

	XmlDocument document = new XmlDocument();
	Rectangle rect = new Rectangle(300,500,1000,500);

3. Возможности макросов урезаны до предела. Можно лишь объявлять и проверять, есть ли такой-то — такой-то макрос, а некоторые макросы объявляются через настройки компилятора. Всё!

	#define M
	...
	#if M
		double M = 53;
	#endif

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

Вот какими безопасными могут быть макросы.

4. Что многие, многие вещи уже качественно сделаны в C#, а нормальный, солидный стиль делает их еще и самодокументирующимися, понятными, особенно после прочтения документации.

Полно еще классов и пространств имен в основных сборках, которые еще не изучены вами. И это еще только основные сборки, а есть еще множество других!

В основных сборках сделаны:
  • все базовые преобразования между строковым, числовым и логическим типами, преобразования находятся в классе Convert (System)
  • Вменяемые коллекции (System.Collections*)
  • Классы Xml (System.Xml*)
  • Сетевые классы (System.Net*)
  • Многопоточность (System.Threading*)
  • Классы по работе с процессами, диагностикой производительности, отладке (System.Diagnostics*)
  • и даже компилятор CodeDom для языков .NET! (System.CodeDom)
  • и многое другое

А есть еще много дополнительных, среди них можно выделить 2 основные, используемые в оконных приложениях: System.Windows.Forms* (по работе с GUI) и System.Drawing* (по работе с графикой)

Также, есть некоторые полезные встроенные вещи в языке, которых нет в C++:
  • встроенная конструкция foreach ? перечисление элементов коллекции
  • автоматический сборщик мусора, нам не нужно вручную освобождать память, а выделяется очень быстро, и не надо делать собственное управление памятью
  • свойства ? вместо того, чтобы писать методы доступа, можно писать свойства, которые объединяют в себе два метода доступа и не имеют параметров, все более лаконично, особенно сказывается на красоте интерфейса класса
  • всё наследует от объекта и может быть превращено в строку переопределяемым методом ToString()

	class Example {
		int X{get; set;}
		int Y{get; set;}
		object Object{
			get{return object;}
			set{object = value==null ? new object() : value;}
		}
	}
	...
	foreach(String arg in args) {
		Console.WriteLine( arg );
	}
	...


5. Что нельзя просто так взять и побаловаться указателями. Вам нужно для этого разрешить небезопасный код в настройках компиляции и обозначить класс как небезопасный, добавив «unsafe» в список его модификаторов. И только после этого можно будет с ними работать.
Кроме того, невозможно, невозможно! ? получить адрес константы или переменной только для чтения, что делает невозможным её изменение! ? и мы можем спокойно спать сладким сном, зная, что C# не даст константы и неизменяемые переменные в обиду всяким садистам, ой, то есть, изменять!

	unsafe class C {
		int* n;
		static void Main() {
			byte* n = (byte*)(5);
			n = (byte*)(n+3);
		}
	}

6. Что элементы перечислений остаются в контексте перечислений и не вываливаются в глобальный контекст. И они пишутся (по соглашению) в таком же стиле ? стиле C# ? как и имя содержащего их перечисления.

	enum DayOfWeek {
		Monday = 1, Tuesday, Wednesday,
		Thursday, Friday, Saturday,  Sunday
	}

В C# вообще ни одна функция/переменная/константа не может находиться вне класса.

7. Что многие ошибки, которые программист по невнимательности пропускает, на выявление которых можно определить алгоритм, C# обнаруживает и говорит, что это ошибка, прерывая компиляцию, если эта ошибка влияет на работу, а некоторые остаются как предупреждение, если не влияют. То есть, ошибки по невнимательности.

Среди ошибок:

  • возврат значения не во всех условных ветвях, либо отсутствие возврата значения
  • использование не определенной переменной
  • неявное преобразование большего по размеру в ОЗУ числа в меньшее по размеру в ОЗУ ? double==>float / long==>int==>short==>byte и т.п., а также знакового и беззнакового друг в друга: int<=>uint, short<=>ushort и т.п.; а также bool<=>число
  • неявное преобразование bool<=>число
  • перепрыгивание с одной метки case на другую, если данная не закрыта командой прерывания break, при том, что-то содержит или последняя.

Среди предупреждений:

  • не использованная переменная, функция, событие (приватная или локальная)
  • не достижимый код ? значит, перед ним стоит команда перехода (return/goto/break/continue)


Кроме того, параметры функции могут иметь один из двух модификаторов:
1. ref ? передача ссылки, в объявлении и передаче ссылке переменную нужно явно указать это слово впереди.
2. out ? то же самое, но переменная еще и может быть не объявлена

	void F(ref int x,ref int y){ ... }
	void O(out float j,out float k){ ... }
	...
	int x = 0, y = 0;
	F(ref x,ref y);
	int j,k;
	O(out j,out k);

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

Есть и другие полезные ограничения:

  • порядок с операторными функциями ? они все обязаны быть статичными
  • нельзя создать функцию/переменную/константу вне класса (ведь на любые действия или данные можно найти класс)

Подведём итоги


C# нам говорит: программируйте в удовольствие, у меня для этого всё есть: замечательные правила языка, правила именования, а также разные полезные библиотеки.

C# нас учит: используйте правильный стиль именования, забудьте про всякие подчеркивания, они излишни; забудьте про свободно гуляющие глобальные переменные и функции, у нас все находится в классах; не считайте ограничения надуманными, а считайте их правильными и упорядывающими ваше мышление, пишите по правилам и вы обретете нирвану!

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

Вывод


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

Комментарии (53)


  1. poxu
    17.12.2015 11:27
    +30

    У вас проблема с названием статьи. Статью надо было назвать по другому. А именно «Почему С++ — отстой и чем его заменить».

    Не реализован класс массив? Нету нормальной мапы? А вы точно про С++?


    1. onto
      17.12.2015 19:47
      +2

      Ну вброс же.


  1. laphroaig
    17.12.2015 11:28
    +21

    Добро пожаловать в клуб самоубийц… нашел, блин, с чем на C++ наезжать


    1. bonext
      17.12.2015 11:36
      +1

      уважаю ваш ник :D


    1. withkittens
      17.12.2015 13:18
      +1

      Но ведь… автор из песочницы… его пригласило НЛО…


      1. laphroaig
        17.12.2015 13:34
        +8

        Ну не повезло автору, бывает
        image


  1. WingedFlame
    17.12.2015 11:37
    +7

    Если Вы привыкли, что Вас должен язык вести за ручку по достаточно очевидным (в контексте написания чего-то сложнее лабораторных работ в универе) вещам и бить по рукам за то, что Вы не можете следовать элементарному Code Style — это, в первую очередь, Ваша проблема.
    И уж тем более не проблема языка в том, что Вы не смогли понять работу стека и не нашли, что «умный» массив в C++ называется vector, а также не приметили «словарь» и «карту» (хотя про set и map написано, наверное, в каждом учебнике по C++).
    C++ предполагает, что разработчик достаточно умный, чтобы не играться с преобразованием типов без полного понимания всех последствий, и чтобы в случае объявления аргумента-ссылки явно указывать «const» при необходимости. Ну, и к тому, что если метод принимал аргумент по значению, не стоит менять его на принимающий значения по ссылке без предварительного согласования всего вызывающего этот метод кода.


    1. vladon
      18.12.2015 09:55
      +1

      По поводу const и способа их изменить через пень-колоду: const и прочие ограничения придуманы не для спасения от самого себя, а для спасения от законов Мёрфи.


  1. AngelOfSnow
    17.12.2015 11:39
    +38

    Мощнейший анализ двух ЯП


  1. ilmirus
    17.12.2015 11:43
    +19

    Жалко, что хаб «Юмор» удалили.


  1. nnesterov
    17.12.2015 11:48
    +4

    >> нельзя создать функцию/переменную/константу вне класса (ведь на любые действия или данные можно найти класс)
    Да, но всех настолько достало постоянно писать Math.sin(), что в C# 6.0 ввели статические импорты.


    1. Oxoron
      17.12.2015 13:34
      +2

      Я так мечтал об этой фиче… Но как только она появилась понял, что она слишком непривычна.
      Коллега сделал класс, где достаточно часто мелькали

      if(IsNullOrWhiteSpace(arg))
      
      После прочтения пришло осознание, что
      if(String.IsNullOrWhiteSpace(arg))
      
      гораздо читабельнее.
      Хотя математикам проще, да.


      1. monah_tuk
        18.12.2015 08:17

        вот, кстати, есть как минимум одно исследование, которое говорит, что_underscore_нотация_иди_snake_case_позволяет_легче_читать_код: ieeexplore.ieee.org/xpl/articleDetails.jsp?reload=true&tp=&arnumber=5521745

        Ваш пример в snake_case:

        if (is_null_or_white_space(arg))
        


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


        1. vladon
          18.12.2015 09:53

          Google использует snake_case для функций, которые выполняются быстро, а CamelCase — для функций, выполняющихся долго и медленно. Тоже интересный подход.


        1. Oxoron
          18.12.2015 10:17

          Речь шла не про Style Guide, а про импорт статических классов.

          Style guide-a в идеале придерживаются все участники проекта, независимо от личных предпочтений.

          Импорт статики — дело (пока) сугубо добровольное, хотя R# и подталкивает пользоваться фичей. Проблема в том, что читать код с импортированными статическими классами непривычно.
          Рассмотрим стандартные библиотеки. String.IsNull() и IsNull(), File.ReadAllBytes() и ReadAllBytes, Path.GetFileName() и GetFileName() — методы в любой из этих пар мне кажутся разными, читаемость падает, поэтому я не импортирую String, Path, File классы. В своих библиотеках я предпочитаю extension методы, и импорт статики ну нужен. В итоге фича применима только для ограниченного числа статических классов вроде Math, поскольку при его импорте читаемость кода не ухудшится.

          При этом года через три этой фичей будут пользоваться гораздо активнее (в силу стандарта R#), и тогда привычки придется поменять.


    1. vlivyur
      18.12.2015 10:45
      -2

      Ещё раздражает когда this. не пишут.
      А за Point Point я пока не придумал как поквитаться.


  1. xorbot
    17.12.2015 11:55
    +4

    У С++ порог вхождения «немного» больше.


  1. Sing
    17.12.2015 12:05
    +6

    Язык программирования — это инструмент. Он не должен вас ничему учить и ничего вам говорить, а наоборот: он предоставляет свой набор возможностей, и вы решаете, что из них вам нужно. Если язык позволяет больше, чем вам нужно (например, «Что можно именовать типы, методы и переменные маленькими буквами»), вы просто не используете эти возможности. Это плюс, а не минус.


    1. Mingun
      17.12.2015 20:14
      -1

      Тут самое главное, чтобы язык грамотно давал по рукам, когда хочется сделать чего-то «просто так», не подумав, но в то же время позволял извернуться в любой ситуации без излишнего brainfuck-ства. Так что в чем-то концепции шарпа правильные (особенно с приведением типов, впрочем, так во многих молодых и не очень (Java) языках).


  1. isotoxin
    17.12.2015 12:19
    +27

    Нытье человека, освоившего C#, но которому лид дал задание что-то написать на C++


    1. inborn_killer
      17.12.2015 13:01
      +8

      Я подозреваю, что автор ещё не дорос до работы, уж очень школьный стиль опубликованного «анализа».


      1. isotoxin
        17.12.2015 13:14
        +4

        Студент, или недавний студент. Недавно принят на работу. Месяц кодил тулзу для внутренних нужд с интерфейсом на DevExpress. Прилетел таск на основной код на C++, с которым знаком только в теории. Практика ужаснула.
        Я сейчас описал реальный случай.


        1. inborn_killer
          17.12.2015 13:31

          Повезло мне, что нам в университете преподавали плюсы. Не пишу на них уже лет пять-семь и не очень тянет, но уважение с тех пор осталось )


  1. svistkovr
    17.12.2015 12:44
    +4

    Школьник освоил C# (ибо программист старой школы мельком знает про C/C++ и не обсирает почем зря).
    Всю жизнь прожил по типу

    C# нам говорит: программируйте в удовольствие, у меня для этого всё есть: замечательные правила языка, правила именования, а также разные полезные библиотеки.

    И вдруг понадобилось подключить какую-то библиотеку или SDK на древнючем C++!!!… и тут мир перевернулся.
    Не стоит так обсирать сей замечательнейший язык.
    Вы даже не представляете какой нирваны можно можно достигнуть по пути C/C++.


  1. tangro
    17.12.2015 12:50
    +17

    Образцово-показательный хабрасуицид. Ждём дальнейших откровений на тему «почему виндовс мастдай», «mongodb лучше, чем mysql» ну и что-то на тему почему тёплое более круглое, чем мягкое.


    1. inborn_killer
      17.12.2015 12:56
      +2

      По-моему этот пост уже переплюнул упомянутые вами темы )


  1. AWE64
    17.12.2015 12:52
    +2

    В чём вообще смысл таких сравнений? Шарп и плюсы — языки под разные задачи. На C# вы при всем желании не напишите, скажем, операционную систему. Инструмент правильный подобрать настоящий джедай должен.


    1. vladon
      18.12.2015 09:51

      Справедливости ради, нужно отметить Cosmos, SharpOS и Singularity :-) Но…


  1. Lite4
    17.12.2015 13:02
    +2

    «именование как C#», есть camel case, есть snake case, а про такое именование не слышал.


    1. Ununtrium
      17.12.2015 13:57

    1. Ununtrium
      17.12.2015 14:02

      Точнее, это Visual Studio Style, если не ошибаюсь. У C# разные имплементации, и стиль тоже отличается (от рекомендованного в Mono, допустим).


  1. Ostrie_Brevna
    17.12.2015 13:27
    +2

    Несколько более обширное сравнение C++, C# (а также Objective C и Java): hyperpolyglot.org/cpp (с примерами кода и таблицей)


  1. x512
    17.12.2015 13:48
    -11

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


  1. Nanako
    17.12.2015 13:52
    +3

    Вот это по нашему. Ни одного слова про CLI и рантайм. Вы уж определитесь что сравниваете.


  1. Ununtrium
    17.12.2015 13:56
    -3

    Раз в пару месяцев появляется (пролазит в обсуждаемое) такая статейка. И главное, почти все время C++ и C#, нет бы Javascript и LISP или Visual Basic и Пролог. C++ народ защищает, С# не очень, видимо сказывается меньшая популярность. И конечно, любая такая статья неполна без пары мудрых комментариев что для каждой задачи свой инструмент.


    1. poxu
      17.12.2015 14:07
      -1

      Да! Как эти коментарии достали!


    1. Nanako
      17.12.2015 14:31
      +3

      Просто идиотизм статьи зашкаливает. Есть С# у которго свой рантайм и С++ который компилируется в «нормальный» бинарник. Есть С++ CLI который вроде как С++11, но там таблица с расхождениями от стандарта на 10 листов А4, есть managed C++ — кадавр для рантайма .NET, есть еще куча тонкостей. Дак либо сравнивайте сам синтаксис языков и не пихайте в сравнение стандартные бибилитеки. Либо сравнивайте CLR и С++ — «какая удобная стандартная библиотека». Есть еще другие варианты, а тут бред на уровне «крокодил больше круглый чем зеленый, щас я вам это докажу!». Нет бы тиснуть статью что например в C# override был уже давно, а в С++11 появился впервые и о чудо, это поддерживается реализацией MSVS начиная с 2010, с минимальным отходом от стандарта.


      1. kosmos89
        17.12.2015 21:09
        +1

        >Есть С++ CLI который вроде как С++11, но там таблица с расхождениями от стандарта на 10 листов А4
        C++/CLI — это не C++11, это набор расширений для оного, чтобы из нативного C++ кода можно было взаимодействовать с управляемым, а из управляемого — с нативным. Другими словами, C++/CLI — это надмножество C++.

        >есть managed C++
        Это старая версия C++/CLI.


        1. Lol4t0
          17.12.2015 21:56

          Есть еще C++-cx, который Nanako имел в виду, видимо


          1. Nanako
            18.12.2015 06:57

            Именно. Просто я на C# в основном пишу, а в вариантах С++ путаюсь постоянно. С и С++ я по большей части через вообще через nmake собираю. Больших проектов на них у меня нет, в итоге мне понятнее получается.


  1. xaizek
    17.12.2015 15:11

    вы не можете никак взять и объявить поле, скажем, size size или point point
    Можем (небольшое пояснение), но не стоит так делать. Да, сработает не всегда, но это не «никак».


  1. EndUser
    17.12.2015 17:06
    +2

    С++ позволительно критиковать только двумя способами:

    1) C++ N лучше в указанных вопросах, чем бардак C++ N-1. И это интересная и полезная критика.

    2) C++ применительно к специфической задаче хуже, чем _insert_language_name_here_. И это бестолковая публичная критика, позволенная только в узких кругах, когда junior хочет применить слишком мощный язык к узкой задаче.

    В остальных случаях это holy-war и flame, иногда с утерей кармы.


  1. Arakel
    17.12.2015 18:39
    +9

    Пример с константным указателем сделал мой день в стиле «я докажу вам что ваш язык отстой, потому что я не умею им пользоваться».


    1. onto
      17.12.2015 19:53
      +3

      Видно, что у него и с C# то плохо, особенно повеселил пример с «макросами».


      1. Mingun
        17.12.2015 20:19
        +1

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


        1. Andy_Ion
          18.12.2015 08:19

          У меня до сих пор требует, что, тем не менее, не огорчает :)


      1. Arakel
        17.12.2015 21:26
        -6

        #include <iostream>
        #define profit int main(int argc, char *argv[]) {std::cout << "MACROS MASTER!!!";  return 0; }
        profit
        

        Шах и мат, Автор!


  1. Daniro_San
    18.12.2015 07:51
    +3

    Вы о соглашениях именования хоть немного слышали?
    Они не ограничиваются только Pascal style — https://msdn.microsoft.com/ru-ru/library/ms229043.aspx
    Ну а все остальные «доводы» просто смешны.
    К вашему сведению уже давно есть C++11, C++14 с строгими перечислениями (enum class) и умными указателями.
    Не нужно смешивать C++ и C# — первый это продолжатель Си, второй был создан как помесь Delphi с синтаксисом Java что бы и вы могли «программировать».


  1. vladon
    18.12.2015 09:44
    +2

    Так толсто, что даже тонко.


  1. vladon
    18.12.2015 10:05
    +2

    Выделение памяти (new/malloc) жутко тормозит! Вы сами, сами! должны делать управлятель памятью (ничего себе задача!), либо довольствоваться медленной работой


    Так в C# выделение тоже тормозит, просто это делается, например, при запуске.
    Открою секрет: в C# выделение памяти происходит точно так же через malloc (желающие могут погуглить точное название функции из WinAPI), как и в любой операционной системе.


    1. vladon
      18.12.2015 10:12

      Ну и это претензия не к собственно языку, а к инфраструктуре.

      На C++/CLI всё так же, как в C#.


  1. Oxoron
    18.12.2015 10:28
    +4

    Кстати, неплохой вариант попасть на хабр. Пишем подобную статью, получаем приглашение от НЛО, обнуляем карму, ждем пару недель. На выходе нулёвый акк. Profit же.


    1. KvanTTT
      21.12.2015 15:10

      Есть менее трудозатратные способы. Например, написать о чем-нибудь интересном…