Навеяно вот этой статьей.

Существует три мнения относительно производительности C++ и C#.

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

Люди из первой категории все время пытаются доказать свою правоту. При этом приводят примеры оптимизированного кода на C++ и самого пессимизированного кода на C#.

Пример «типичного» сравнения


image
Любой программист, который знает C# сразу увидит две ошибки:
  1. Вызов GC.Collect, который сводит на нет любые оптимизации сделанные в рантайме для сборки мусора.
  2. Использование for цикла, который гарантированно не устраняет проверки границ на каждое обращение к массиву.

При этом в реальности ни один C#-программист не напишет код с GC.Collect и очень малая часть программистов допустит ошибку в цикле for.
Какой смысл сравнивать гарантированного неэффективный код на C# даже с обычным кодом на C++? Разве что доказать свою точку зрения.

Честное сравнение


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

Для примера буду использовать ту же саму пузырьковую сортировку массива.

Тесты для C++


Для случая C++ протестирую три варианта:
  1. С-style массив (указатель)
  2. std::array
  3. std::vector

Каждый тест будет запускаться по 100 раз и результат будет усредняться.
Код измерения
std::chrono::high_resolution_clock::duration measure(std::function<void()> f, int n = 100)
{
	auto begin = std::chrono::high_resolution_clock::now();
	for (int i = 0; i < n; i++)
	{
		f();
	}
	auto end = std::chrono::high_resolution_clock::now();
	return (end - begin) / n;
}


Код теста для C-style
Код
void c_style_sort(int *m, int n) 
{
	for (int i = 0; i < N - 1; i++)
		for (int j = i + 1; j < N; j++) {
			if (m[i] < m[j])
			{
				int tmp = m[i];
				m[i] = m[j];
				m[j] = tmp;
			}
		}
}

void c_style_test()
{
	int* m = new int[N];

	for (int i = 0; i < N; i++)
	{
		m[i] = i;
	}
	c_style_sort(m, N);
	delete[] m;
}


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

Код теста для std::array
Код
void cpp_style_sort(std::array<int, N> &m)
{
	auto n = m.size();
	for (int i = 0; i < n-1; i++)
		for (int j = i + 1; j < n; j++) {
			if (m[i] < m[j])
			{
				int tmp = m[i];
				m[i] = m[j];
				m[j] = tmp;
			}
		}
}

void cpp_style_test()
{
	std::array<int, N> m;

	for (int i = 0; i < N; i++)
	{
		m[i] = i; 
	}
	cpp_style_sort(m);
}


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

Кто знает C++ уже поняли, что std::array не вызывает аллокаций, а сам массив хранится в теле класса, то есть в стеке в этом примере. std::array должен стать однозначным лидером в этом забеге.

Код теста для std::vector
Код
void vector_sort(std::vector<int> &m)
{
	auto n = m.size();

	for (int i = 0; i < n - 1; i++)
		for (int j = i + 1; j < n; j++) {
			if (m[i] < m[j])
			{
				int tmp = m[i];
				m[i] = m[j];
				m[j] = tmp;
			}
		}
}

void vector_test()
{
	std::vector<int> m;
	m.reserve(N);

	for (int i = 0; i < N; i++)
	{
		m.push_back(i);
	}
	vector_sort(m);
}


Код полностью аналогичен варианту с std::array. Но std::vector — изменяемый массив, в отличие от std::array. Поэтому vector использует динамическую память для хранения массива и должен честно проверять выход за границы.

Тесты для C#


Также сделаю три теста:
  1. Обычный массив
  2. Обычный массив с использованием unsafe (указателей)
  3. System.Collections.Generic.List

В отличие от «типичного» подхода сравнения производительности, я не буду вызывать GC.Collect, а положусь на рантайм.

Тесты будут прогоняться многократно, поэтому уборки мусора будут случаться и учитываться в замерах.
Код измерения
        static long Measure(Action f, int n = 100)
        {
            var sw = System.Diagnostics.Stopwatch.StartNew();
            for (int i = 0; i < n; i++)
            {
                f();
            }
            return sw.ElapsedMilliseconds / n;
        }


Код теста для обычного массива
Код
static void ArrayTest()
{
    var m = new int[N];
    for (int i = 0; i < m.Length; i++)
    {
        m[i] = i;
    }
    ArraySort(m);

}

static void ArraySort(int[] m)
{
    for (int i = 0; i < m.Length - 1; i++)
        for (int j = i + 1; j < m.Length; j++)
        {
            if (m[i] < m[j])
            {
                int tmp = m[i];
                m[i] = m[j];
                m[j] = tmp;
            }
        }
}


Очень важный момент — в ограничении цикла for стоит m.Length (минус константа). Такой паттерн определяется JIT и устраняет проверки на границу массива.

Код теста для unsafe
Код
static unsafe void UnsafeTest()
{
    var m = new int[N];
    fixed(int* ptr = &m[0])
    {
        for (int i = 0; i < N; i++)
        {
            ptr[i] = i;
        }
        UnsafeSort(ptr, N);
    }
}

static unsafe void UnsafeSort(int* m, int n)
{
    for (int i = 0; i < n - 1; i++)
        for (int j = i + 1; j < n; j++)
        {
            if (m[i] < m[j])
            {
                int tmp = m[i];
                m[i] = m[j];
                m[j] = tmp;
            }
        }
}


Сортировка выглядит так же, только используются указатели, и гарантированно никаких проверок (и никаких оптимизаций). Я не стал делать тест с fixed array, потому что в реальности его не встретишь.

Код теста для List

Код
        static void ListTest()
        {
            var m = new List<int>(N);
            for (int i = 0; i < N; i++)
            {
                m.Add(i);
            }
            ListSort(m);

        }

        static void ListSort(List<int> m)
        {
            var n = m.Count;
            for (int i = 0; i < n - 1; i++)
                for (int j = i + 1; j < n; j++)
                {
                    if (m[i] < m[j])
                    {
                        int tmp = m[i];
                        m[i] = m[j];
                        m[j] = tmp;
                    }
                }
        }


В отличие от обычного массива, для List нет оптимизаций в JIT, поэтому значение длины списка храним в переменной.

Результаты


Я компилировал код в Visual Studio 2015, запускал под .NET Framework 4.6. Везде настройки Release, по умолчанию.

Получил вот такие результат:
Тест x86 x64
(С++) С-style 55ms 55ms
(С++) std::array 0ms (52ms) 65ms
(С++) std::vector 100ms 65ms
(C#) массив 67ms 90ms
(C#) unsafe массив 63ms 105ms
(C#) List 395ms 390ms

В режиме x86 оптимизатор полностью выкинул сортировку для std::array, поэтому получилось 0. В реальности работает чуть быстрее, чем C-style массив за счет отсутствия аллокаций.

Выводы


  • Для обоих языков идиоматичный код — самый эффективный (вообще странно если бы это было не так)
  • C# медленнее C++ в таких задачах на 20%-50% (это верхняя граница)
  • Для x64 оптимизировать надо отдельно (очевидно, но все же)

Код можно найти тут — github.com/gandjustas/PerfTestCSharpVsCPP

Что осталось «за кадром»


В C# массив — ссылочный тип. Поэтому без проблем можно передавать в любую функцию. В C++ все контейнеры ведут себя как «размерные» типы и копируют все содержимое при передаче в качестве параметра. Нужно очень внимательно писать код для C++, чтобы не копировать лишний раз массивы. Зачастую придется прибегать к умным указателям, которые несут дополнительный оверхед.

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

Update


По просьбам читателей изменил и дополнил тесты:
  • Использовал std::swap вместо ручного обмена в C++ коде
  • Сделал вызов .at для вектора вместо [], чтобы он проверял границы в релизной сборке
  • Добавил проект с .NET Native

Результаты получились такие:
Тест x86 x64
(С++) С-style 60ms 52ms
(С++) std::array 51ms 60ms
(С++) std::vector 147ms 81ms
(C#) массив 67ms 90ms
(C#) unsafe массив 63ms 105ms
(C#) List 395ms 390ms
(C# + .NET Native) массив 62ms 59ms
(C# + .NET Native) unsafe массив 63ms 52ms
(C# + .NET Native) List 274ms 282ms

Получается в .NET Native быстродействие такое же, как у C++.
Из-за тормозов в дебаге для std::swap отлаживать стало невозможно.

Исходники там же: github.com/gandjustas/PerfTestCSharpVsCPP

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


  1. Wedmer
    07.09.2015 17:16
    +13

    В C# массив — ссылочный тип. Поэтому без проблем можно передавать в любую функцию. В C++ все контейнеры ведут себя как «размерные» типы и копируют все содержимое при передаче в качестве параметра. Нужно очень внимательно писать код для C++, чтобы не копировать лишний раз массивы. Зачастую придется прибегать к умным указателям, которые несут дополнительный оверхед.

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


    1. gandjustas
      07.09.2015 17:32
      +7

      Да-да, а еще у опытных разработчиков рабочих день из 30 часов и они цитируют Кнута наизусть в обратном порядке.

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


      1. maaGames
        07.09.2015 17:51
        +15

        Достаточно пару сотен раз обжечься и проблема забытой ссылки пропадает сама собой. Со мной в последний раз это случилось четыре года назад. Вернее, шесть лет назад, но два года эта ошибка не проявляла себя. Вектор передавался по значению, но почти всегда был из малого числа элементов и на производительности заметно не сказывалось. Лишь когда при определённом использовании размер увеличился до нескольких сотен элементов и производительность экспоненциально падать начинала (столь глупая ошибка была в рекурсивной функции), то косяк обнаружился. И сразу же был исправлен.
        Столь громко осуждаемые и обсуждаемые ошибки с указателями, ссылками и прочим — по большей части удел студентов. Спустя несколько лет практики их уже на уровне инстинктов не допускаешь.А ещё помогает RAII и следование codestyle.
        По поводу оверхеда умных указателей — в шарпе-то этот оверхед есть всегда и везде (unboxed не учитываем), а в Сишке только там, где пожелает программист.


        1. gandjustas
          07.09.2015 23:11

          Достаточно пару сотен раз обжечься и проблема забытой ссылки пропадает сама собой.

          Без комментариев.

          Эта пара сотен раз во сколько сотен тысяч долларов выльется?


          1. Katasonov
            08.09.2015 12:03
            +2

            Обычно пару сотен раз обжигаются быстро и в универе.


            1. gandjustas
              08.09.2015 12:30

              В универе не учат тому, что потом придется использовать в работе. Увы.


              1. JediPhilosopher
                08.09.2015 13:15
                +3

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

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

                Так что универы тоже разные бывают.


                1. gandjustas
                  08.09.2015 13:27
                  +1

                  Прекрасный пример. В C# такой проблемы вообще бы не случилось.


                  1. lasalas
                    08.09.2015 16:17
                    +1

                    Зато в C# можно наколоться с boxing/unboxing, хотя масштаб разрушений обычно меньше.


                1. koshak
                  08.09.2015 13:31

                  З — Зависть


              1. 0xd34df00d
                08.09.2015 14:30

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

                Во время обучения в универе просто это делать проще и разумнее, чем уже потом на работе.


                1. Mrrl
                  08.09.2015 14:33
                  +2

                  В универе приходится отвлекаться на учёбу :(


                  1. 0xd34df00d
                    08.09.2015 14:34

                    Таки учёбу и работу над своими хоббями можно вполне успешно совмещать. Всё ж учёба не 16 часов в сутки сжирает.


        1. FiresShadow
          08.09.2015 07:14
          +12

          Достаточно пару сотен раз обжечься и проблема забытой ссылки пропадает сама собой.

          [Ирония]А ещё достаточно 10-20 лет пописать на ассемблере, и проблема сложности читаемости и написания кода на ассемблере отпадает сама собой. Главное следовать codestyle. А ещё код на ассемблере можно оптимизировать лучше, чем код на С++.
          Чудаки, придумали тут несуществующую проблему. Терпенье и труд все перетрут! Долой автоматизацию труда программиста! Даёшь ассемблер! [/Ирония]


          1. FiresShadow
            08.09.2015 07:42
            +3

            [Ирония]Чудная это обезьяна! Вместо того, чтобы по деревьям лазать, сбивает плоды палкой-копалкой. Ленивая какая-то. Сильные обезьяны так не делают! Достаточно пару сотен раз слазить на дерево, мышцы накачаются, и это не будет уже проблемой. Последний раз у меня были сложности с залезанием на дерево шесть лет назад. Терпенье и труд все перетрут! Долой автоматизацию труда обезьяны![/Ирония]


            1. maaGames
              08.09.2015 15:10
              +1

              Без иронии.
              Чудная обезьяна целую неделю страдала-голодала, но продолжала бросать палку-копалку в пробегающих мимо антилоп. Другие обезьяны над ней смеялись, ведь палка-копалка нужна, чтобы сбивать бананы, а не антилоп. А она продолжала бросать, пока не научилась попадать в цель и жрать питательное мясо. А другие обезьяны продолжали над ней смеяться и стали зваться вегетерианцами.

              Вот вы реально проблемы на пустом месте придумываете. Студенты косячат и ругают указатели и прочее, но это совсем не проблема. Опытный программист просто физически не сможет написать код с вышеозвученными проблемами, потому что подсознание спать не даст, пока не исправишь эту ошибку. Про codestyle я написал не ради красивого словца, а по делу. Если чётко сказано, что входные параметры должны быть ко константной ссылке, а выходные по ссылке или указателю, то косяк просто не пройдёт code review. Не говоря о том, что в блокнотах кодят только обезьяны и любая современная IDE обнаруживает большинство ошибок (вы ведь читаете предупреждения компилятора?), и ещё больше ошибок отлавливаются специальными утилитами (блюющим единорогом) и профайлером.

              Но уровень вхождения в C# несколько ниже, с этим соглашусь. Можно говнокодить не отстреливая ноги из верёвки.


              1. FiresShadow
                08.09.2015 16:01
                +1

                Необходимость работать с памятью вручную нагружает программиста дополнительной работой. Нужно написать деструктор, конструктор копирования (без него деструктор и копирование будут работать некорректно), следить что delete вызывается там где нужно, следить передаются у вас аргументы в функцию по ссылке или через копирование в стек и т.п.
                Вы более шести лет этим занимались, и поэтому вам этот рутинный труд кажется чем-то само-собой разумеющимся. Ну и эффективность вашего труда вас тоже не сильно беспокоит.
                То, что нужно вручную делать монотонный труд, который можно легко автоматизировать — это проблема. Иное дело, что иногда в силу обстоятельств нужно закрыть глаза на эту проблему, потому что по-другому сделать не получится. Но от этого неудобство не перестаёт быть неудобством.
                То, что вы в течении шести лет писали конструкторы копирования, не даёт вам права называть студентами и второсортными программистами тех, кто не хочет заниматься их написанием. Ну если не занимается человек микроконтроллерами, то зачем ему выполнять этот рутинный труд? Ради выигрыша в 10%-20% в скорости из-за того, что в С++ нет всевозможных проверок на выход за границы массива (не забываем про JIT-компилятор)? Нет, спасибо, я предпочитаю наличие таких проверок на уровне языка.


                1. maaGames
                  08.09.2015 16:15
                  +3

                  Нет почти по всем озвученным тезисам.
                  Начну с конца.
                  Я не называл студентами и второстепенными тех, кто не хочет писать конструкторы, я называл студентами и второстепенными программистами тех, кто не может поставить символ & и делает из этого трагедию. Впрочем, я не называл никого второстепенными и студентами называл не в обидном смысле слова, а в смысле временного отсутствия опыта.
                  Конструкторы и деструкторы нужны не только и не столько для освобождения памяти. Скажу больше, сейчас у меня в проекте около полутора тысяч файлов, при этом new и delete используются буквально в десятке из них. Вызывать вручную delete? Ну написал его один раз в деструкторе — руки не отвалятся.
                  Если не выделять память через malloc/new, а использовать контейнеры, то писать конструкторы копирования(а ещё и присваивания!) не нужно. Если следовать RAII, то и деструкторы не всегда нужны, по крайней мере delete в них писать точно не придётся.
                  Выход за границы массива проверяются в дебаге и в релизном коде уже в принципе не должно быть выхода за границы (я метатель). При желании, можно проверять выход за границы массива и в релизном коде (at вместо []). Это С++, тут можно практически всё, было бы желание.
                  В современном программировании под «ручным управлением памяти» подразумевается, что программист в любой момент времени знает, существует ли объект или нет и знает, когда именно этот объект будет уничтожен. Может сам выбрать для этого момент, чтобы был наименьший удар по производительности. Может вообще не разрушать объект. А может положиться на RAII и вообще быть не в курсе, что такое ручное управление.


                  1. FiresShadow
                    08.09.2015 17:52
                    -2

                    Скажу больше, сейчас у меня в проекте около полутора тысяч файлов, при этом new и delete используются буквально в десятке из них.
                    Понятно, вы не испытываете проблем с управлением памятью в куче, потому что ваш codestyle подразумевает отказ от выделения памяти в куче. Ну так, с этого и следовало начинать. А если человек не хочет ни в чём себя ограничивать, и не хочет заниматься лишним рутинным трудом, предпочитая автоматизацию? Ну и да, в этой рутине тоже можно допустить ошибку.

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

                    я называл студентами и второстепенными программистами тех, кто не может поставить символ & и делает из этого трагедию
                    На эту тему я уже высказался. Можно лазать по деревьям и гордиться своим умением не наступать на тонкие ветки и не будить спящих на дереве змей, а можно сбить фрукт палкой-копалкой. Вы же почему то высказываетесь против палки-копалки. Ваша позиция: «Будь мужиком — лезь на дерево. Не умеешь лазать по дереву — не мужик». Тут абсолютно неважно, умеет ли человек, пользующийся палкой-копалкой, не будить спящих змей на дереве. Важно, что вы выступаете против прогресса.
                    Не спорю, в редких ситуациях умение лазать по дереву может оказаться очень кстати. Но это не повод каждый раз лезть на дерево и заниматься рутинным трудом, когда этого можно и не делать. Просто признайте, что вам лень изучать принцип работы палки-копалки и занимайтесь вашим рутинным трудом дальше на здоровье. Зачем тормозить развитие других соплеменников? Если человек не хочет заниматься рутинным трудом, а хочет уделять больше времени более творческим задачам, и современные технологии (в том числе быстродействие современных компов) ему это позволяют, то почему бы и нет???


                    1. FiresShadow
                      08.09.2015 17:58
                      -1

                      Добавлю, что в редких случаях и знание машинных кодов нужно. Но это не оправдывает позицию: «Будь мужиком — пиши на машинных кодах. Тот, кто не знает машинных кодов на уровне подсознания — не мужик.»


                    1. maaGames
                      08.09.2015 18:04
                      +2

                      Я себя ни в чём не ограничиваю! Благодаря stl и прочим контейнерам отпадает необходимость в ручном выделении/удалении памяти для коллекций. Штучные объекты создаются менеджерами объектов(как раз те редкие файлы с new/delete), но это сделано не ради отказа от new, а из-за фабрик полиморфных объектов. Кстати, есть множественное и пирамидальное наследование, но проблем с ним тоже нет. Это я вспомнил ещё один популярный камень в огороде С++.


                      1. FiresShadow
                        08.09.2015 18:46

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


                        1. maaGames
                          08.09.2015 18:57
                          +1

                          Деструкторы нужны НЕ для того, чтобы вызвать в них delete. Например, сокеты я тоже в деструкторах закрываю. И с файлов блокировку снимаю. И с тех же мьютексов. Я не знаю, есть ли в C# деструкторы, если нет, то пичалька, придётся каждый раз в блок finally писать код, который можно один раз в деструктор написать.
                          Мне не нужно ВСЕГДА передавать классы по ссылке, потому что в некоторых случаях эффективнее по значению. Что? В шарпике тоже можно по значению передавать, но только структуры? А вот в плюсиках можно передавать так, как хочешь. А ещё можно передавать по значению, но при этом копирования объекта не будет, потому что изначально будет использоваться тот объект, который потом вернётся из функции. Да, С++ и так может, потому и компилируется код долго, что он много чего может.
                          Я окидываю код взглядом сотни, а то и тысячи раз. Не ради ошибок работы с памятью — этот класс ошибок у меня практически устранён на уровне архитектуры приложений. Я в принципе стараюсь не писать такой код, в котором могут быть ошибки работы с памятью. То же касается и ошибок переполнения буфера.
                          Анализаторы кода запускаю раз-два в месяц (не считая того анализа, на который способен компилятор при каждой компиляции). Логические ошибки обнаруживаются периодически. Неправильная инициализация обнаруживается. Дублирующиеся и не эффективные сравнения обнаруживаются. С памятью пока ничего связанного не обнаруживалось.
                          У Макконелла по этому поводу очень хорошо было написано: Выделил память, сразу же напиши код её освобождения. Всё проблема решена.


                          1. lair
                            08.09.2015 19:35
                            +2

                            JFYI: в C# есть и деструкторы, и детерминированное освобождение ресурсов.


                            1. maaGames
                              08.09.2015 19:53
                              +1

                              Как там может быть детерминированное освобождение ресурсов, если там сборщик мусора?
                              Про деструкторы — спасибо. Теперь вдвойне забавно выглядят крики о нудном создании деструкторов в плюсах.


                              1. FiresShadow
                                08.09.2015 20:38

                                Как там может быть детерминированное освобождение ресурсов, если там сборщик мусора?
                                А по вашему закрытие файлов и соединений (connection) можно сборщику мусора доверить? Такие ресурсы нужно как можно раньше освобождать.

                                Теперь вдвойне забавно выглядят крики о нудном создании деструкторов в плюсах.
                                Финализаторы в С# не занимаются непосредственным освобождением памяти в куче. Да и используют их довольно редко.


                                1. maaGames
                                  08.09.2015 20:45

                                  > А по вашему закрытие файлов и соединений (connection) можно сборщику мусора доверить?

                                  Не вижу связи между закрытием соединения и освобождением памяти. И вообще, закрытие сокетов или файлов я уже использовал в качеств аргумента для создания деструктора в С++ — не засчитано. Своё придумывайте.)


                              1. lair
                                08.09.2015 20:55
                                +3

                                Как там может быть детерминированное освобождение ресурсов, если там сборщик мусора?

                                Да легко, типичное кооперативное поведение. Сначала объявим класс, заинтересованный в детерминированном освобождении:

                                class DeterministicResource: IDisposable
                                {
                                  void IDisposable.Dispose()
                                  {
                                     //освобождаем ресурсы
                                  }
                                }
                                


                                Теперь используем объект такого класса (при условии, что мы хотим детерминированного поведения):

                                using(var r = new DeterministicResource())
                                {
                                  //делаем что нам надо с ресурсом
                                }
                                


                                Прелесть в том, что как только мы покинули using (причем покинули любым способом — просто вышли за границу, сделали return, бросили exception), компилятор C# гарантирует вызов метода Dispose. Вторая прелесть в том, что если мы при этом используем только управляемые ресурсы, то если вызова Dispose не произойдет (например, пользователю класса не важное детерминированное поведение), ресурсы все равно будут собраны, просто позже.

                                Про деструкторы — спасибо. Теперь вдвойне забавно выглядят крики о нудном создании деструкторов в плюсах.

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


                                1. maaGames
                                  08.09.2015 21:00

                                  Например, деструктор может делать то же самое, что Dispose, без необходимости наследоваться от IDisposable. Я там оговорился и вместо «освобождение памяти» написал «освобождение ресурсов». В контексте сборки мусора и управления памятью речь шла о памяти, а не о ресурсах вообще. GC сработает так, как ему приспичет и тогда, когда ему приспичет. В С++ момент освобождения памяти детерменирован, если не используется сборщик мусора.


                                  1. lair
                                    08.09.2015 21:02

                                    Ну, если вам очень надо детерминированное освобождение памяти, то есть GC.Collect(). Другое дело, что не надо этого в .net делать, не идиоматично это.

                                    Я говорил именно о ресурсах.


                              1. 0xd34df00d
                                08.09.2015 21:38

                                Я тут рискну высказать такую крамольную мысль, с которой уже как-то тут не соглашались, но тем не менее.

                                Вопрос в определении детерминированности. Я настаиваю, что имеет смысл рассматривать, гм, локальную детерминированность — это когда при взгляде на достаточно мелкий кусок кода можно делать о нём выводы, и с этой точки зрения shared_ptr'ы не сильно лучше.

                                Поглядите на этот кусок кода и скажите, умрёт foo в конце функции или нет.

                                void foo(const std::shared_ptr<Foo>& foo)
                                {
                                    bar(foo);
                                }
                                


                                1. maaGames
                                  09.09.2015 15:02

                                  В данном случае ответ однозначно нет (передан по ссылке, косяк в примере). А вот умрёт ли он после возврата из функции сказать сложнее, для этого нужно глянуть на счётчик ссылок в указателе.
                                  О детерминированности. Умный указатель (объект, на который он ссылается, если точнее) будет разрушен в тот момент, когда счётчик ссылок обнулится. Детерменированно? Абсолютно. Локальная переменная будет разрушена при выходе из области видимости(RAII) или при вызове delete. Тоже абсолютно детерменированно. При использовании сборщика мусора можно определённо сказать лишь то, что пока объектом пользуются — он точно существует. И может существовать какое-то время после того, как им уже никто не пользуется.


                                  1. 0xd34df00d
                                    09.09.2015 15:09

                                    В данном случае ответ однозначно нет (передан по ссылке, косяк в примере).

                                    Скорее в формулировке, вы в следующей фразе ответили именно на тот вопрос, который я имел ввиду.

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

                                    Разве сборщики мусора недетерминированны? Я не крупный специалист в этой теме, но, если я правильно всё понимаю, то при одинаковом ходе выполнения программы в одинаковых условиях (при равном объёме доступной системной памяти, например) работа GC разве не будет также одинаковой?

                                    Ну и толку с этой детерминированности, если она разумно и локально размышлять о программе и её поведении всё равно не даёт зачастую, как в примере выше, а размышлять нелокально неудобно: у людей attention span маленький, а для машин там какой-нибудь комбинаторный взрыв числа вариантов control flow пойдёт. Не панацея, в общем, как бы мне, как любителю и поклоннику C++, не было печально.


                          1. FiresShadow
                            08.09.2015 20:24

                            Выделил память, сразу же напиши код её освобождения.
                            Если у вас объект создаётся в куче через фабрику, то для соблюдения этого принципа у вас используются менеджеры объектов, как я понял с ваших слов. Эти менеджеры объектов надо как-то оповещать, чтобы они поняли, что пора сделать delete. Создание менеджера и его оповещение — это дополнительные приседания. Опять таки создание объектов в куче у вас наверное не всегда через фабрику делается. Если всегда, то пложение фабрик где надо и не надо — опять таки дополнительные приседания, ну или в чём то вы себя всё же ограничиваете в плане использования кучи.

                            Деструкторы нужны НЕ для того, чтобы вызвать в них delete.
                            А если в конструкторе был выделен массив в куче, то где прикажете его освобождать? Отдельную функцию завести? И в чём выгода, почему не в деструкторе?

                            А ещё можно передавать по значению, но при этом копирования объекта не будет
                            Что? Передача по значению происходит путём копирования полей объекта в стек. Если изменение переданного по значению параметра приводит к изменению исходного объекта, значит одно из полей объекта — указатель, и вы изменили память по этому указателю. Но даже этот указатель копируется. Если вы в функции этому указателю присвоите новый адрес, то в исходном объекте адрес указателя не изменится.

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

                            Да, С++ и так может, потому и компилируется код долго, что он много чего может.
                            Вы уверены, что дело в богатстве возможностей языка, а не в компиляторе? Кстати, C# тоже умеет много чего, чего не умеет С++: рефлексия, динамическая кодогенерация, динамик прокси (на основе кодогенерации), мок-объекты (на основе динамик-прокси)


                            1. maaGames
                              08.09.2015 20:39

                              > А если в конструкторе был выделен массив в куче
                              vector и никаких куч

                              > Передача по значению происходит путём копирования полей объекта в стек.
                              С++11 и конструктор перемещения. Если компилятор сочтёт эффективным, то вместо копирования будет редактирование того объекта, который будет возвращён из функции, а не объекта, который будет затем скопирован.

                              > что столь опытный программист, коим вы себя позиционируете
                              Я ни слова не говорил о своём абсолютном опыте, а лишь относительно автора статьи. Например, С++14 я вообще не знаю. C# я вообще почти не знаю, поэтому без деструктора варианта кроме finally не вижу (мне уже сказали, что деструктор есть, всё ОК).

                              > C# тоже умеет много чего, чего не умеет С++
                              С++ тоже это всё умеет. Только это придётся самому запрограммировать…


                              1. FiresShadow
                                08.09.2015 21:26

                                vector и никаких куч

                                У вектора есть деструктор. И вектор хранит свои элементы в куче.

                                придётся каждый раз в блок finally писать код, который можно один раз в деструктор написать
                                Стандартное средство борьбы с дублированием кода — вынесение дублирующегося фрагмента в отдельную сущность. От языка практически не зависит.

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


                                1. Door
                                  09.09.2015 14:04
                                  +1

                                  И вектор хранит свои элементы в куче.

                                  Это если по-умолчанию, передаём что-то типа вот такого аллокатора — и всё на стеке


                                1. maaGames
                                  09.09.2015 15:20

                                  > У вектора есть деструктор. И вектор хранит свои элементы в куче.
                                  В управляемых языках тоже есть и куча и стек и регистры процессора, но речь же о ручном освобождении памяти.

                                  > вынесение дублирующегося фрагмента в отдельную сущность
                                  И ручное прописывание этой функции в finally, что то же самое дублирование, только в меньшем масштабе. Мне уже ответили, что в шарпе есть деструкторы, так что этот пункт с повестки снимается.

                                  > И как это вы интересно будете делать рефлексию?
                                  > научите рефлексии без препроцессора (это из коммента ниже, но я только раз в 5 минут писать могу, так что тут отвечу)
                                  Почему в Шарпе можно дописывать аттрибуты и свойства и всякое разное, чтобы включить поддержку какой-нибудь рефлексии, а плюсы должны быть прям по учебнику и даже без препроцессинга? На С/С++ можно запрограммировать практически всё что угодно, вопрос только в велосипедах и костылях. Раз в С++ до сих пор нет рефлексии, значит, она не настолько востребована в высокопроизводительных приложениях. Либо её нельзя эффективно реализовать в принципе. Я не пользовался рефлексией в других языках, так что не знаю обо всех сферах её применения.
                                  С другой стороны, чем словарь из строк и функторов не рефлексия? Типа map<string,functor)? Повторюсь, я не знаю, что такое рефлексия и описание из википедии похоже именно на добавление/подмену методов класса.


                                  1. lair
                                    09.09.2015 15:40

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

                                    Подозреваю, что вам все-таки лучше сначала узнать, что такое reflection, и как он устроен в .net, прежде, чем спорить на эту тему. Ничего «дописывать» не надо, рефлексия работает всегда и доступна из коробки.

                                    Раз в С++ до сих пор нет рефлексии, значит, она не настолько востребована в высокопроизводительных приложениях.

                                    Тут возникает разумный вопрос: а «высокопроизводительные приложения» — это единственная область применения С++?

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

                                    Если вкратце, то reflection (по крайней мере, в .net) — это способность в рантайме получать метаданные кода (как выполняемого, так и нет), и потом выполнять код на основании этих метаданных. Типичный сценарий — имея на входе класс (не объект), получить список всех свойств, определенных в этом классе, затем сопоставить их с входными данными (скажем, xml-файлом), и создать объект этого класса, где свойства будут заполнены входными данными.


                                    1. maaGames
                                      09.09.2015 15:59

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


                              1. 0xd34df00d
                                08.09.2015 21:34
                                +1

                                С++ тоже это всё умеет. Только это придётся самому запрограммировать…

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

                                Лучшее, к чему я пришёл на данный момент — это что-то вроде такого, это чтобы не писать ручками SQL для операций со структуркой Record. ORM этакий прям.

                                Не было бы необходимости поддерживать boost 1.57, можно было бы взять форму BOOST_FUSION_ADAPT_STRUCT из 1.58 без указания типов полей.

                                Ну и выглядит стрёмно это всё.


                                1. Pushkoff
                                  09.09.2015 13:07

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

                                  P.S. отсутствие рефлексии в С++ конечно расстраивает…


                                  1. 0xd34df00d
                                    09.09.2015 14:16

                                    Почему же меньшее? Надо как минимум написать будет руками все SQL-запросы, а лучше их вынести в ресурсы и подгружать оттуда, следить за этим, модифицировать систему сборки…

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


                                1. Door
                                  15.09.2015 09:51

                                  кхм, как вы умудряетесь так много и постоянно комитить )?


                                  1. JIghtuse
                                    15.09.2015 09:55

                                    Напишите свой Leechcraft — поймёте =)


                                  1. 0xd34df00d
                                    16.09.2015 14:01

                                    Писать код люблю просто :)


        1. bigfatbrowncat
          14.09.2015 02:42
          -4

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

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

          В один не очень прекрасный момент я обнаружил, что программа моя падает при завершении. Пока работает — всё окей. А на выходе «на посошок» — SEGFAULT. Думаю, все с таким сталкивались.

          Долго я ломал голову, в чем дело. На что только не думал. Все деструкторы по 20 раз проверил, брейкпоинтов понаставил… Всё тщетно. Решение обнаружилось при внимательном перечитывании кода, к которому я пришел от отчаяния. Один объект получал в конструкторе ссылку на другой и тут же ее сохранял. То есть, конструкция такого вида:

          public: A(B& b): m_b(b) {...}

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

          И, не говоря мне ни слова, компилятор честно скопировал объект b. Тот был для копирования не предназначен и при деструкции я получил ошибку двукратного освобождения памяти (которая под MINGW, почему-то, обратилась SEGFAULT-ом).

          Сейчас я, конечно, понимаю, что в классе B можно было запретить копирование, создав неимплементированный оператор присвоения и копирующий конструктор (ибо он действительно был не предназначен для копирования). И, конечно, имей я чуть больше опыта, я бы, в первую очередь посмотрел именно в сторону ссылок, а не деструкторов.

          Всё это справедливо. Я своей глупости не отрицаю.

          Но есть и другая правда. А именно: язык, в котором один забытый символ в типично используемой конструкции приводит к появлению трудновылавливаемой ошибки времени исполнения с молчаливого одобрения компилятора — плохой язык. Он спроектирован из расчета на непогрешимость разработчика. А разработчик — человек, ему свойственно ошибаться и платить головой (или целым днем работы) за мелкую опечатку — совсем не комильфо.

          Я навскидку предложу 2 варианта решения проблемы, которые, почему-то, не пришли на ум господину Страуструпу (или он, почему-то, не счел их приемлимыми).

          1. Запретить «неявный» копирующий конструктор для объектов и то же самое — с оператором присвоения. Хотя бы заставить разработчика явно написать «разрешаю копирование» в декларации класса, чтобы исключить «недоразумение по умолчанию». Я бы не поленился пару слов написать — это быстрее, чем полдня дебажить.
          2. (Прекрасное решение, реализованное в языке C#) Поделить все объекты строго на две категории — те, которые всегда передаются только по ссылке и те, которые передаются исключительно по значению. В 99% случаев никому не нужно один и тот же объект передавать и так, и так. Для остального 1% нетрудно создать метод «clone» или что-то в этом духе.

          И таких примеров много. C++ плох тем, что он, помогая разработчику писать код, не мешает ему делать серьезные ошибки. Он не защищает от ситуации, когда ошибка в одном модуле приводит к падению в совсем другом. Иногда проще переписать программу с нуля, чем поймать случайный memory corruption crash…


          1. Wedmer
            14.09.2015 02:53
            +2

            По сравнению с C, в ногу таки выстрелить сложнее. Но если вам это удастся, то попрощайтесь со всей ногой.

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


            1. bigfatbrowncat
              14.09.2015 03:11
              -3

              В Си нет ООП, сравнение некорректно.

              Я еще раз повторю — я свой косяк не отрицаю. Но вот в остальном я с вашей логикой совершенно несогласен:

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

              В языке C++ — именно так. В нормальном ЯП — совершенно неверное утверждение. Я не был в армии, но полагаю, что когда (если) личному составу выдается заранее заряженное оружие, предохранитель должен быть выставлен по умолчанию. Спуск можно нажать случайно. Можно просто уронить оружие. Мало ли, какие случайности бывают…
              В языке Паскаль, например, по умолчанию был выставлен range checking. Да, его можно отключить, но если ты это сделал, то либо ты знаешь, что творишь, либо — «сам себе злобный Буратино». А когда у меня вся панель управления забита «красными кнопками» без защиты, то это — не боевая машина для профессионалов. Это — минное поле.

              А теперь — без метафор. Любая система, предназначенная для использования людьми, должна быть спроектирована так, чтобы повышение опасностей и рисков (а не понижение их) достигалось дополнительными усилиями. В областях инженерии, где риск носит фатальный характер, это давно усвоили. Например, на заводах в цехах штамповки и резки станок имеет не одну спусковую кнопку, а две. И расположены они в разных его концах, а нажимать их надо ладонями, одновременно. Как считаете, там много работает идиотов, которые не знают, что руки под нож совать не следует? И тем не менее, одного «понимания» этой банальности работниками инженерам показалось недостаточно — они специально сделали так, чтобы руки были заняты в момент удара.

              В Java есть миллион способов убить программу неопределяемой ошибкой. Но для этого надо как минимум задействовать рефлексию. А лучше — JNI. Еще лучше — динамическую кодогенерацию на JVM. И объем кода, на котором это удастся сделать — тысяча классов. На меньшем вы с легкостью найдете ошибку.

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

              Я честно старался полюбить C++. Изучал его несколько лет (параллельно с C# и Java). Писал что-то на нем. Но всякий раз я втыкался в совершенно непредсказуемые результаты совершенно, на первый взгляд, безобидных действий.


              1. Wedmer
                14.09.2015 10:45
                +1

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


                1. bigfatbrowncat
                  14.09.2015 11:44
                  -1

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

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


                  1. Wedmer
                    14.09.2015 12:44
                    +3

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


                    1. bigfatbrowncat
                      14.09.2015 13:19
                      -3

                      Последние два года я разрабатываю проекты, включающие в себя 2 слоя. Нижний уровень пишется платформонезависимым способом на языке Си. Это обычно высокоскоростной слой, который занимается взаимодействием с графикой или чем-то подобным. Дальше идет JNI-интерфейс. Верхний слой пишется на Java. Там находится вся логика, там если и приходится думать об управлении ресурсами, то только в рамках имплементации интерфейса Disposable.

                      Взаимодействие с ОС осуществляется через JRE, поэтому проект получается кроссплатформенный.

                      При этом критерий использования Си таков: на нем надо писать либо то, что даст этим существенный выигрыш производительности, либо то, что по каким-то причинам не может быть написано на Java (например, OpenGL-вызовы).

                      Java непригодна для оперирования большими массивами данных — она слишком много времени тратит на выделение/освобождение памяти. Но если не тащить в нее многомегабайтные буфера (а в этом обычно нет необходимости), то писать на ней управляющий слой, для которого и нужно ООП — одно удовольствие.

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

                      Так что они превосходно дополняют друг друга.

                      Для разработки я применяю IDE Eclipse, в которой можно одновременно исполнять и отлаживать и C, и Java.

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

                      Писать контроллеры на C++ гораздо труднее. И UI тоже, даже несмотря на такие мощные инструменты, как Qt.


                    1. dougrinch
                      14.09.2015 14:47
                      +3

                      Rust?


                      1. Wedmer
                        14.09.2015 15:09

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


                        1. bigfatbrowncat
                          14.09.2015 19:01
                          -1

                          D — отличный язык. Если бы я сочинял свой, он бы был очень на него похож. Но, увы, инфраструктуры в нем… нет. От слова «совсем». Если бы существовала надежная, нормально доделанная среда разработки, более-менее вменяемая стандартная библиотека, желательно, стандартизованная (или хотя бы популярная) и если бы хоть пара крупных компаний в него вложились, написав на нем что-то крупное… Искренне желаю этому языку всего вышеперечисленного.

                          Rust не знаю, но в лучшем случае все вышеперечисленные комментарии — про него тоже.


                          1. Wedmer
                            14.09.2015 20:10
                            +1

                            По D у вас устаревшие данные.


                            1. bigfatbrowncat
                              15.09.2015 15:33

                              Перепроверил.

                              github.com/DDT-IDE/DDT/blob/latest/documentation/Features.md#features

                              Выглядит уже более-менее симпатично. Но по-прежнему сыро. Можно попробовать написать что-то небольшое на нем. Авось лет через 10 он появится в списке полезных технологий в собеседованиях на технические вакансии.


                              1. Wedmer
                                15.09.2015 17:22

                                Недопроверили.


                                1. bigfatbrowncat
                                  15.09.2015 18:41

                                  Так просветите. Вы же в нем разбираетесь.


                                  1. Wedmer
                                    15.09.2015 19:27

                                    Вы хотя бы сюда заглянули для начала.
                                    А потом wiki.dlang.org/Current_D_Use прочли бы.


                                    1. bigfatbrowncat
                                      15.09.2015 20:40
                                      -1

                                      Да заглядывал. Какой смысл мне от того, что Facebook где-то задействовал D, если я даже не знаю, где?

                                      Остальные названия я не знаю. И, к тому же, сам факт наличия такого списка на сайте языка означает примерно следующее: «Посмотрите, какие мы взрослые, нас даже ФЕЙСБУК заметил!»

                                      То есть попробуйте такой список для того же пресловутого C++ составить. Или для Java.

                                      Понимаете? Для этих языков проще перечислить, что написано НЕ на них.

                                      Я, вместо этого, посмотрел, с чем придется столкнуться разработчику, который захочет писать на D. И вижу я только минимальную поддержку Intellisense в IDE (что, конечно, хорошо), отсутствие, например, рефакторинга кода (что означает, что авторы плагина крупные проекты не пишут), только-только более-менее отлаженную стандартную библиотеку и гордый список «Нас Заметили».


          1. JIghtuse
            14.09.2015 08:22
            +1

            И, не говоря мне ни слова, компилятор честно скопировал объект b.

            Это странно. Что за версия компилятора, какие флаги сборки? Вот пример, у меня он не собирается (gcc 4.9.3):

            ideone.com/M535ZN (clang 3.7)
            ideone.com/42XEHl (gcc 4.3.2)

            Или не было и звёздочки перед m_b? Это уже двойная забывчивость какая-то. Но и такая лечится одним запуском valgrind/cppcheck:
            Cppcheck
            user@host [tmp]$ cppcheck --enable=all copy.cxx
            Checking copy.cxx...
            [copy.cxx:1]: (style) 'class B' does not have a copy constructor which is recommended since the class contains a pointer to allocated memory.
            


            1. bigfatbrowncat
              14.09.2015 10:33
              -2

              Было это пару лет назад. Звездочки перед m_b не было, потому что m_b было ссылкой. Вот только я, честно говоря, позабыл, где именно я амперсанд потерял — в конструкторе, или в декларации ссылки. Скорее, конечно, второе… Детали уже не помню. Никакого C++11 — только старый стандарт.

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


              Я как раз этим и руководствовался — классы-модули связывал по ссылкам, а не по указателям.

              Как реализовать запрет копирования, я знаю. Тогда, возможно, еще не знал, но это не важно.

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

              Возьмите школьника и крутого профессионала. Дайте каждому из них Java и C++. И адекватную каждому задачу. И вы увидите, что на Java каждый напишет сообразный своему уровню программу. Код, написанный школьником на Java, будет ужасен, неэффективен и переполнен антипаттернами. Но он будет работать. Потому что все ошибки, которые создаст «юное дарование», оно же при должном усердии сможет починить. У него всё будет под контролем.

              А вот на C++ он не напишет ничего. Потому что любая программа сложнее «скажите А, скажите Б, вот вам А+Б» у него будет крэшиться и требовать для исправления проблемы более глубокого уровня понимания, чем тот, которым он владеет на данном этапе. Он впоследствии, возможно, поймет, что сделал не так. Но будет поздно.

              Мне трудно приводить себя в пример, так как Java я начал изучать, уже умея программировать, зная ООП и много других умных слов. Но я хорошо помню, что на Паскале (который идеологически ближе Java) мне было гораздо проще добиться рабочего кода, чем на Си.

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


              1. 0xd34df00d
                14.09.2015 13:00
                +2

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

                Почему это?

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


                1. bigfatbrowncat
                  14.09.2015 13:25
                  -1

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

                  Я сам лет до 15-и не задумывался, для чего нужны эти странные «рога» на противоположной стороне молотка. При этом я с успехом забивал гвозди. Инструмент щедро предоставлял мне тот набор функциональности, который я был способен использовать. Вы вряд ли обрадывались бы, если бы перед использованием дрели вам приходилось сдавать экзамен не только по правилам техники безопасности (тут я ничего против не имею), но и, скажем, по ее инженерной конструкции.

                  Мы каждый день применяем разные системы, каждый — в меру своего понимания. Чтобы ездить на автомобиле попрежнему достаточно не путать педали и знать ПДД, а не разбираться в конструкции системы впрыска топлива (старые советские модели не рассматриваем).

                  (Утрирую для понимания) Представьте себе язык программирования, который требует знания высшей математики для того, чтобы написать на нем тетрис. Как считаете, хороший он? Удобный? Я сомневаюсь.


                  1. 0xd34df00d
                    14.09.2015 13:37
                    +3

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

                    Вот и у C++ нет такого режима.

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

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

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


                    1. bigfatbrowncat
                      14.09.2015 19:14
                      -1

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


                      Лучше. Потому что этот школьник, написав работающую программу, одну, другую, третью, постепенно будет учиться, развиваться. И в итоге вырастет в специалиста, который создает классные продукты. Все мы когда-то «забывали объекты из коллекций удалять».

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

                      Хорошо ли это? Я считаю, что когда люди развиваются, а не бросают всякие попытки на старте — это, несомненно, хорошо.

                      Что до Хаскелля, то вы слабовато взяли. Давайте прямо сразу Пролог возьмем. Вот где надо много знать, чтобы простейшую задачу решить. Только почему-то им вообще мало пользуются. И студенты, которым им мозг компостируют, вместо программирования идут компьютерные сети прокладывать. А потом — в менеджеры…

                      C++, в отличие от Хаскелля, позиционируется, как инструмент, пригодный для решения простых задач — UI там писать, игры… И, что характерно, именно это на нем обычно и пишут. Так уж сложилось. Но вы вряд ли найдете вменяемого человека, который станет писать графический редактор или игру на Хаскелле. Разве что из соображений обучения.


                      1. 0xd34df00d
                        14.09.2015 19:21
                        +1

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

                        Это какой-то школьник с завышенным ЧСВ и уверенностью в собственной непогрешимости. Не надо так.

                        И студенты, которым им мозг компостируют, вместо программирования идут компьютерные сети прокладывать. А потом — в менеджеры…

                        Потому что мозги компостировать надо не конкретным Прологом или Хаскелем или C++, а математикой. Компостирование конкретными языками — это уровень ПТУ, а не высшего учебного заведения.

                        C++, в отличие от Хаскелля, позиционируется, как инструмент, пригодный для решения простых задач — UI там писать, игры…

                        А где можно почитать, как позиционируется Хаскель и как позиционируется C++?

                        Оба этих языка вроде как описываются как языки общего назначения, значит, на них обоих можно писать что игры, что UI.

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

                        А почему тех, кто таки станет, вы сразу записываете в невменяемые?


                        1. bigfatbrowncat
                          14.09.2015 19:34

                          Это какой-то школьник с завышенным ЧСВ и уверенностью в собственной непогрешимости


                          Нет. Просто человек слаб. И всегда обвиняет в своей слабости других. А если он еще и неопытен… Он вам ничего не скажет. Просто пойдет писать стихи.

                          Компостирование конкретными языками — это уровень ПТУ, а не высшего учебного заведения.


                          Город Нижний Новгород. Несколько факультетов в ННГУ и НГТУ. Такие вот у нас в стране два именитых «ПТУ».

                          Оба этих языка вроде как описываются как языки общего назначения, значит, на них обоих можно писать что игры, что UI.


                          Можно. Покажите мне крупную коммерческую игру на Хаскелле и я с вами соглашусь, что он для этого удобен. Пишут, что-то больше на C# (Unity), на Java и на Python. А на C++ движки делают.

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

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


                          1. 0xd34df00d
                            16.09.2015 14:05
                            +1

                            Нет. Просто человек слаб. И всегда обвиняет в своей слабости других. А если он еще и неопытен… Он вам ничего не скажет. Просто пойдет писать стихи.

                            Ну и пусть идёт. Предпочту работать с людьми посильнее.

                            Город Нижний Новгород. Несколько факультетов в ННГУ и НГТУ. Такие вот у нас в стране два именитых «ПТУ».

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

                            Пишут, что-то больше на C# (Unity)

                            Обсуждалось же уже вроде, что ядро Unity — на плюсах, на C# очень несущественный (по крайней мере, по части производительности) кусок. Вы тогда уж ещё Lua вспомните.

                            Java и на Python

                            Где посмотреть на крупные коммерческие игры на этих языках?

                            Я думаю, что функциональная парадигма в архитектурном плане менее мощна, чем ООП.

                            Почему?

                            Она не только сложнее для понимания

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

                            но и более хлопотна

                            И это почему?


                      1. Wedmer
                        14.09.2015 20:14

                        У большинства от того, что все работает, будет меньше мотивации повышать качество своего кода. Ведь работает же!


                        1. bigfatbrowncat
                          15.09.2015 15:36
                          -3

                          Мотивация повышать качество кода — резльтат любви к делу и наличия эстетического чувства. Ни то, ни другое не разовьется, если у вас ничего не получается путного с самого начала.

                          У меня работало. И в детстве на Паскале, и в более старшем возрасте на Delphi, затем немного на C#, потом на Java (в том числе, под Android). И иногда на C и C++ работало, но меньше и хуже. Но если C — неизбежное зло для того, кто хочет писать быстрый код под платформу, то в чем неизбежность C++, я так и не понял. Даже сообщения об ошибках при наличии в коде хоть пары шаблонов читать — кошмар сущий.


                          1. 0xd34df00d
                            16.09.2015 14:06
                            +1

                            Моим первым языком был JS. Снежинки в браузере, ощущение феерической нелогичности и костыльности, и так далее. А вот потом я взял книгу по C++, и понеслась…

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

                            Даже сообщения об ошибках при наличии в коде хоть пары шаблонов читать — кошмар сущий.

                            Попробуйте использовать нормальные инструменты вроде clang.


                      1. Chaos_Optima
                        14.09.2015 20:34

                        пригодный для решения простых задач — UI там писать, игры…

                        Эм… с каких пор написание UI и игр перешло в раздел простых задачь?


                        1. Wedmer
                          14.09.2015 20:41

                          С тех же самых пор как и

                          В Си нет ООП


                          1. bigfatbrowncat
                            15.09.2015 15:57
                            -1

                            В Си ООП нет. Это я вам могу сказать после того, как участвовал в течение 2х лет в разработке под платформу BREW (https://en.wikipedia.org/wiki/Brew), которая написана на Си и в которой ООП было на всех уровнях.

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

                            Теоретически можно поддерживать любую парадигму на любом языке. Можно писать ООП на Си, можно писать ASM-way на Java. Просто это запредельно неудобно.


                            1. Wedmer
                              15.09.2015 17:29

                              Вы написали чепуху. Ни в одном языке нет ООП. ООП реализуется при помощи языка. Причем он может и не быть объектно-ориентированным. А в С есть структуры, в которые можно укладывать указатели на функции. Quake 2 по сути был написан с использованием ООП но на C.
                              ,


                              1. Mrrl
                                15.09.2015 17:33

                                Вы под ООП понимаете только наличие виртуальных функций?


                                1. Wedmer
                                  15.09.2015 17:50

                                  А вы сделайте ревью кода Q2 и сами решите. Это был всего навсего пример того, что для ООП не всегда нужен OOЯП.


                              1. bigfatbrowncat
                                15.09.2015 18:49
                                +1

                                Я написал не чепуху. Просто у нас с вами разные понятия.

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

                                Си не предназначен для ООП. В нем нет ни понятия класса, ни понятия инкапсуляции, ни полиморфизма. В рамках Си можно создать «игрушечный» полиморфизм, организованный вами же как набор указателей на функции. Можно написать #define CLASS struct. Можно много чего сделать. Но от этого сам язык не станет удобнее при использовании этих возможностей.

                                Компилятор не обругает вас за попытку вызова private-метода, система контроля типов не подскажет вам, что вы присваиваете яблоки к крокодилам. Всё то, что является основными преимуществами современного ООП, совершенно не будет работать.

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

                                Вот именно это всё я и подразумевал под фразой «В Си ООП нет».


                                1. Wedmer
                                  15.09.2015 19:42

                                  Попытка выкрутиться провалена. Вы расскажите это разработчикам Linux kernel и Asterisk.


                                  1. bigfatbrowncat
                                    15.09.2015 20:34

                                    Дорогой друг! Во-первых, не грубите. Я не выкручиваюсь, а дискутирую. Высказываю те аргументы, в которые верю.

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

                                    А в третьих, тот факт, что во многих проектах, в которых требуются запредельные условия (например, сочетание низкого уровня и сложной архитектуры), используются инструменты, лишенные удобства для разработчика, не отрицает того, что они неудобны. Кстати, в ядро Линукса C++ не пускают. Что тоже намекает…

                                    Еще раз: когда на использование языка обрекает нужда и выбора нет, используют то, что есть. Вот, на веб-клиенте используют JS. Ужасный язык — но что делать!?

                                    Вы, ради бога, пишите, на чем вам удобнее. Я, к слову, вас судить не пытаюсь. И искренне вам желаю удачи в том, что вы любите — разработке крупных проектов с ООП на чистом Си и игровых движков класса ААА с браузерами на C++. И никогда не разочаровываться в этом деле.

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


                                    1. Wedmer
                                      15.09.2015 22:25

                                      Я вам не грубил. Просто у нас с вами разные понятия.

                                      В том то и проблема, что ваши аргументы больше смахивают на чисто ваше мнение. Хоть на статьи какие ссылки бы дали.

                                      Слишком много разных причин, почему C++ нет в ядре Linux. От личной неприязни Линуса до тупой несовместимости. В LKML FAQ все расписано.

                                      Хорошо оптимизированный код чаще красивее, чем что то неповоротливое.


                                      1. bigfatbrowncat
                                        15.09.2015 22:45
                                        -2

                                        Мои аргументы смахивают на мое мнение, поскольку им и являются. Я стараюсь опираться в споре на свой опыт. Гуглом могут пользоваться все.

                                        А ваши аргументы смахивают на кучу расхожих стереотипов, подкрепленных расхожим оптимизмом. Если бы вы привели, как я,.пример из своего собственного опыта, это было бы интересно. А говорить «C++ крутой, потому что на нем кучу всего пишут» могу и я. Только вот я считаю, что основных причин его распространения 3.
                                        1. Совместимость с Си
                                        2. Свобода от патентных притязаний (вся платформа, стандарт и основные библиотеки полностью открыты)
                                        3. Причина рекурсивная — моя любимая. C++ популярен оттого, что он популярен. На вопрос, на чем можно написать всё на свете, вопрошающему говорят: «Возьми кресты. Они сложные, но уж если освоишь, то удешь богом».

                                        А еще — это соображение вас вряд ли убедит, поскольку оно уж совсем умозрительное, но я всё же скажу: чем универсальнее инструмент (а вы, надеюсь, не будете спорить, что в универсальности с C++ мало, кто может соревноваться), тем он менее удобен для каждого конкретного случая. В низком уровне мы превращаем C++ в Си, на высоком уровне мы пытаемся из него сотворить что-то наподобие C# или Java. Вот только Си проще и быстрее компилируется (просто за счет более простого синтаксиса), а в C# и Java более качественная защита от глупостей.

                                        Хорошо оптимизированный код чаще красивее, чем что то неповоротливое


                                        Где-то слышал фразу: «оптимизация — это то, чем начинают заниматься программисты, когда код слишком красив».

                                        А если серьезно, то красив хорошо спроектированный код. На любом языке. Если хотите пример того, что я считаю красивым кодом, загляните в исходники Eclipse Platform. 15 лет истории и IBM как основной автор. Результат прекрасен. Его оптимизировали — но оптимизации носили именно архитектурный характер. И такие оптимизации лучше делать на Java — легче. А те оптимизации, о которых мы с вами говорили — это т.н. микрооптимизации — выиграть 10% производительности, чуть-чуть изменив последовательность выделения памяти и поменяв местами две командочки. Вот это я, простите, считаю суетой. Не интересно это.


                                        1. Chaos_Optima
                                          15.09.2015 23:06
                                          +1

                                          Ну вот что за чушь вы несёте.

                                          В низком уровне мы превращаем C++ в Си, на высоком уровне мы пытаемся из него сотворить что-то наподобие C# или Java.

                                          Может вы так и делаете, но нормальные программисты используют С++ как С++. По долгу работы мне приходится использовать С#, Pyton, mel помимо С++, и на какждом из этих языков я пишу так как нужно писать на том или ином языке, никогде не писал на С++ как на С или на С#. Зато на предыдущей работе работал с людьми, которые писали на С++ как на яве, которые использовали огромные иерархии, и вместо указателей на функцию\метод использовали интерфейс IWorld, про переопределение операторов\шаблоны вообще неслышали, а для того чтобы добавить класс в фабрику приходилось править 5 файлов вместо того чтобы один раз написать макрос и шаблон, и использовать каждый раз в одном месте.

                                          Вот когда пишешь на одном языке как на другом, вот тогда и появляются проблемы, возможно вы пытались в своей практике использовать С++ как С# или Java, отсюда у вас и все проблемы с этим языком.


                                          1. bigfatbrowncat
                                            16.09.2015 03:29
                                            -2

                                            Я очень жалею, что в Java нет переопределения операторов. Она бы стала лучше от этого.
                                            Я очень жалею, что ни в Java, ни в C++ нет свойств. Без них код более унылый. В C++ я свойства эмулировал с помощью шаблонов и макроопределений, но это было не то…
                                            Я очень жалею, что ни в C++, ни в C# нет внутренних нестатических классов. Более того, большинство людей, которые не исали на Java, даже не понимают, что это такое и для чего они могут быть полезны…

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

                                            Но это всё — мелочи.

                                            С точки зрения проектирования Listener в Java и event в C# — совершенно одно и то же (да, я знаю, что event-у можно назначить сразу несколько обработчиков, Listener тоже можно сделать таким, просто это — менее удобно). И многословность Java тоже не особенно приятна, но она компенсируется мощнейшими средствами IDE.

                                            Все три языка на самом деле очень сильно похожи. Поэтому их можно и нужно сравнивать. И сравнение это будет явно не в пользу C++, когда дело касается надежности кода. Единственное, чем C++ может похвастаться — это отсутствием дополнительного runtime-а для исполнения кода.

                                            И еще.

                                            Я сначала изучил C++ (по крайней мере на уровне книги Герберта Шилдта), а только потом появился язык C#. А про Java я вообще узнал только 5 лет назад.

                                            Почему вы считаете, что если для меня эти языки похожи, я не понимаю между ними разницы? Давайте просто допустим, что эта разница несущественна.


                                            1. Chaos_Optima
                                              16.09.2015 04:10

                                              Но это всё — мелочи.

                                              Вообще не понимаю к чему вы привели эти примеры, я говорил не про фичи конкретных языков а про процесс проектирования приложения. (и да внутринние классы в С++ это friend классы, ну и да всё что вы привели фигня, единственное чего не хватает С++ это рефлекшена)
                                              С точки зрения проектирования Listener в Java и event в C# — совершенно одно и то же

                                              Ну вообщето далеко не одно и тоже, Listener в яве требует наследования от интерфейса. Отсюда в яве рождается куча ненужных однострочных интерфейсов, либо же интерфейсов при реализации которых приходится писать пустые функции, в С# же и в С++ этого можно избежать. Программисты на проекте были java way, а потому использовали интерфейсы, а т.к. городить кучу интерфейсов им было лен, они решили использовать С стиль и передавать идентификатор и указатель на войд. Вот что в нашем случае означало писать на С++ как на яве и как на С, и именно из-за вот таких вот «решений» вырисовываются поистине эпические ошибки, патерны это конечно хорошо, но их тоже нужно уметь и писать и применять, в зависимости от языка.
                                              И многословность Java тоже не особенно приятна, но она компенсируется мощнейшими средствами IDE.

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

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

                                              Вы не понимаете между ними разницы, потому что вы считаете что эта разница несущественна.

                                              Я сначала изучил C++ (по крайней мере на уровне книги Герберта Шилдта), а только потом появился язык C#. А про Java я вообще узнал только 5 лет назад.

                                              А я начинал с Delphi а после 5 лет когда поступил в универ познакомился с С++ (на уровне книг Страуструпа, Майерса, Александреску) и прочими языками, а после 5 лет обучения на этих языках в универе, я 6 лет работаю с С++, и попрежнему продалжаю учится программированию. Только вот я не понимаю как эта информация поможет вам? Также как не понимаю зачем вы это написали мне.


                                              1. bigfatbrowncat
                                                16.09.2015 10:33
                                                -1

                                                Окей. Давайте тогда я тоже вспомню, что в школе программировал на Delphi. А когда увидел C++, он мне показался очень запутанным и неудобным. Учить я его начал в первую очередь именно потому, что не видел альтернативы. Когда появился C#, я эту альтернативу увидел. Но я еще достаточно долго пытался иногда писать программы на C++ целиком. Всякий раз получалось хлопотно и времени уходило больше, чем на C#.

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


                                                Серьезно? Вот уж я не знал! Последние 3 года пишу сперва под Android, сейчас портирую яву на новую платформу, был даже контрибьютором в стандартную библиотеку альтернативной Java-машины Avian и — ужас — не знал, что Listener — это анонимный локальный класс.

                                                Вы понимаете, что с точки зрения архитектуры приложения не имеет значения, создается в данном месте анонимный класс, указатель на функцию, определенный через typedef или делегат? Ну не важно это. Главное — что тут имеет место механизм callback-а.

                                                Все эти три языка на самом деле сильно разные, пичально что вы это не видите

                                                Конечно они разные и я это вижу! Но если вы мне дадите программу на C#, я переведу ее вам на Java, воспользовавшись терминами Java и использовав ее преимущества, но программа при этом почти не изменится. То же самое можно сказать про C++. Только там будет сложнее с низкоуровневым дизайном, поэтому кусок кода, возможно, придется загнать под JNI (и эффективнее).

                                                Вы не понимаете между ними разницы, потому что вы считаете что эта разница несущественна

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

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

                                                Большая часть ваших аргументов (про скорость и управление памятью) верна. Это — те причины, по которым я часто использую JNI. Но вот это:

                                                а ещё мультиплатформенностью

                                                насмешило. Честно. Я лет пять искал способ научиться написать проект на g++ так, чтобы потом нормально собрать его под Windows. Или вы мне сейчас начнете про ANSI рассказывать? Давайте я тогда вам в ответ расскажу про прекрасный модификатор «b» в fopen, который, если забыть его на Windows, приведет к тому, что из вашего прочитанного бинаря волшебным образом исчезнут все символы с кодом 13. Я как-то долго отлаживал кусок libcore, который портировал с Linux на Windows и не мог понять, почему у меня картинка не читается с диска. Повеселился на славу.

                                                Единственный по-настоящему кроссплатформенный язык в этой тройке — это Java. И то только если вы используете «родную» библиотеку классов от Oracle. Возьмите стек технологий, на которых основан eclipse — будет вам мультиплатформенность.

                                                Только не надо мне говорить про Qt. Как только он станет частью C++ или хотя бы обзаведется лицензией, позволяющей его использовать в проектах любой степени коммерциализованности без всяких приседаний перед авторами и выплат, я рассмотрю его как приемлимую альтернативу. Кстати, в нем есть кроссплатформенные файловые потоки?


                                                1. Chaos_Optima
                                                  16.09.2015 11:01

                                                  Окей. Давайте тогда я тоже вспомню, что в школе программировал на Delphi.

                                                  Вы хотя бы до конца комментарий прочитали? Зачем вы пишите эту инфу???
                                                  это анонимный локальный класс.

                                                  И что? От этого не изменится тот факт, что этот класс должен реализовывать интерфейс.
                                                  Вы понимаете, что с точки зрения архитектуры приложения не имеет значения, создается в данном месте анонимный класс, указатель на функцию, определенный через typedef или делегат? Ну не важно это.

                                                  В том то вся и фишка, что важно, каждый элемент должен выполнять свою функцию.
                                                  Конечно они разные и я это вижу! Но если вы мне дадите программу на C#, я переведу ее вам на Java, воспользовавшись терминами Java...

                                                  Практически любой код, на любом языке, можно переписать на другом, но это не значит что языки похожи, каждый язык используется там где он нужен, я могу дать вам кусок рендера на С++, но когда вы его перепишите то получится что 80% кода будет написано на JNI, и какой тогда смысл брать яву?
                                                  Я умею использовать все эти три языка

                                                  Не видно, судя по той чуше что вы пишите, вы знаете только яву.
                                                  Я лет пять искал способ научиться написать проект на g++ так, чтобы потом нормально собрать его под Windows.

                                                  мда, это говорит лишь о ваших способностях, а не о языке.
                                                  Давайте я тогда вам в ответ расскажу про прекрасный модификатор «b» в fopen

                                                  В очередной раз хотите похвастаться своей безграмотностью в С++? Я не против. ))
                                                  Единственный по-настоящему кроссплатформенный язык в этой тройке — это Java. И то только если вы используете «родную» библиотеку классов от Oracle. Возьмите стек технологий, на которых основан eclipse — будет вам мультиплатформенность.

                                                  Не видел ни одного примера, на яве для IOS, xbox, ps. И где ваша хвалёная мультиплатформенность?
                                                  Только не надо мне говорить про Qt.

                                                  Если бы я говорил про какую-то универсальную библиотеку то я скорее взял бы буст.
                                                  Кстати, в нем есть кроссплатформенные файловые потоки?
                                                  Есть, а чем вам не угодили потоки из stl?


                                                  1. 0xd34df00d
                                                    16.09.2015 14:20
                                                    +1

                                                    Если бы я говорил про какую-то универсальную библиотеку то я скорее взял бы буст.

                                                    Они всё-таки почти ортогональны. На бусте не сделаешь графический интерфейс и не постучишься в БД, на Qt не сделаешь топологическую сортировку, не посчитаешь диаграммы Вороного и не упорешься темплейтами.

                                                    Есть, а чем вам не угодили потоки из stl?

                                                    Мне, мне не угодили! Я так и не осилил их ускорить и избавиться от ненужных в моём случае операций с локалью и чем-то там ещё внутри istream::operator>>(). Пришлось руками mmap()ить.


                                                  1. bigfatbrowncat
                                                    16.09.2015 22:33
                                                    -1

                                                    В очередной раз хотите похвастаться своей безграмотностью в С++? Я не против. ))


                                                    Нет. Просто мне попал в руки кусок кода на C/C++, который был написан для Linux и который надо было портировать на Windows. Увы, код был написан безграмотными разработчиками из компании… как бишь ее… Google, кажется, которые не знали про потоки в stl.

                                                    Лично мне потоки из stl не нравятся двумя вещами: во-первых, они неудобны, во-вторых — медленны. Возможно, так же считали и люди, делавшие backend в libcore.

                                                    Не видел ни одного примера, на яве для IOS

                                                    А вы знаете, какие титанические усилия Apple прикладывает к тому, чтобы не пустить Java на iOS? Они этой конкуренции боятся как чумы. Потому что весь стек технологий (XCode etc.) в подметки не годится оному из Java.


                                                1. 0xd34df00d
                                                  16.09.2015 14:18
                                                  +1

                                                  Я умею использовать все эти три языка

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

                                                  Единственный по-настоящему кроссплатформенный язык в этой тройке — это Java.

                                                  Некроссплатформенный код можно писать и на нём. Лично видел клиент-банк, который дёргает виндовые DLL, отчего код не запускается больше вообще нигде, и одной лишней буковкой b тут не отделаешься.

                                                  Как только он станет частью C++

                                                  Зачем?

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

                                                  А у Оракла у Гуглу иск типа на пустом месте?


                                                  1. bigfatbrowncat
                                                    16.09.2015 22:06

                                                    Иск Оракла Гугл вполне успешно отбил по всем пунктам, кроме сущей ерунды. Никто не может «приватизировать» API. Можно считать проприетарной только реализацию.

                                                    То, что можно некроссплатформенный код писать на чем угодно, я согласен. Но не нужно подменять понятия. Я вам сказал, что Java кроссплатформенна, поскольку на ней надо очень постараться, чтобы написать что-то платформо-специфичное. А если ограничиться чисто Java-инфраструктурой (а там есть очень-очень много кода и от apache foundation и от куч других), то вообще почти невозможно. Конечно, это не отменяет дураков, которые в Java-коде прибавляют бекслеши к путям. Тут уж ничто не поможет.

                                                    Зачем надо, чтобы вся инфраструктура была стандартизована и являлась частью набора инструментов разработчика? Ответ очень простой — чтобы не было зоопарка. Один станарт — один подход — меньше всего изучать. К тому же, чем меньше кода, тем выше его качество. Этим сильна Java. На ней редко кто-то пишет то же самое по второму разу. Просто такая культура.


                                                    1. 0xd34df00d
                                                      17.09.2015 16:11
                                                      +1

                                                      Иск Оракла Гугл вполне успешно отбил по всем пунктам, кроме сущей ерунды. Никто не может «приватизировать» API. Можно считать проприетарной только реализацию.

                                                      А у вас, вот лично у вас, хватит ресурсов на адвокатов, если что, дабы отбиться?

                                                      А если ограничиться чисто Java-инфраструктурой (а там есть очень-очень много кода и от apache foundation и от куч других), то вообще почти невозможно. Конечно, это не отменяет дураков, которые в Java-коде прибавляют бекслеши к путям.

                                                      Бекслеши в путях в жаве — это они дураки, значит, по-вашему. А fopen и b в плюсокоде — ни в коем случае не дурость. Или не дурость — такая дырявая абстракция, которая, к сожалению, есть в ОС.

                                                      Зачем надо, чтобы вся инфраструктура была стандартизована и являлась частью набора инструментов разработчика?

                                                      Да, зачем надо? Зачем надо стандартизовать GUI, работу с графами, математику и кучу всего ещё? Это замедляет прогресс и не даёт права на ошибки, потому что обратная совместимость, которую потом придётся тянуть.

                                                      Ответ очень простой — чтобы не было зоопарка.

                                                      Как будто это что-то плохое.

                                                      меньше всего изучать

                                                      А вот этого я не понимаю, серьёзно. Это же так прекрасно, изучать что-то новое! В этом весь смысл и весь кайф!
                                                      Да даже в мелочах, вот написал я сейчас парсер один с parsec'ом, получил то-то. Теперь в силу ряда причин охота на той же задаче attoparsec попробовать — а какие у него будут сообщения об ошибках при разборе? А получится ли легко и просто перенести код с одного на другой? А какой прирост в производительности и памяти я получу?

                                                      Не, серьёзно, если страшно и неохота что-то изучать, то не надо идти в программисты.

                                                      К тому же, чем меньше кода, тем выше его качество.

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


                                                      1. bigfatbrowncat
                                                        18.09.2015 12:56

                                                        А вот этого я не понимаю, серьёзно. Это же так прекрасно, изучать что-то новое! В этом весь смысл и весь кайф!

                                                        Вот тут вы меня, думаю, поймете, когда перед вами встанет задача написать программу, большую и хорошую, на основе пары-тройки имеющихся open-source — решений и вам, вместо того, чтобы изучать их абстракции, придется разбираться, как их вместе слинковать, чтобы собралось и не падало.

                                                        Я люблю изучать то, что интересно, а не всё подряд. И люблю стабильность. То есть если не хочется писать всё from scratch, то берешь качественно сделанную платформу и не лезешь в нее. По крайней мере, на первом этапе разработки. Понимаете?

                                                        А еще больше я люблю создавать, а не изучать. Как говорится, чукча не читатель…

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

                                                        Странное сравнение. Когда кода мало, а вылизывают его сотни разработчиков, он становится безупречен. Пойдите, попробуйте найти ошибку в ecj, например. А ведь это — компилятор — довольно непростая штука.

                                                        А если бы компиляторов Java было не 2, а 20 (как у Питона, например), то усилия всех этих людей были бы распылены на них и каждый в отдельности был бы хуже.

                                                        В open-source, где в любой момент код можно беспрепятственно форкнуть, конкуренция — зло. Такая вот «коммунистическая» идеология.


                                                        1. 0xd34df00d
                                                          18.09.2015 16:27
                                                          +2

                                                          Вот тут вы меня, думаю, поймете, когда перед вами встанет задача написать программу, большую и хорошую, на основе пары-тройки имеющихся open-source — решений и вам, вместо того, чтобы изучать их абстракции, придется разбираться, как их вместе слинковать, чтобы собралось и не падало.

                                                          Почему-то такого опыта у меня нет. Не поделитесь своим? Просто ради интереса.

                                                          И люблю стабильность.

                                                          Стабильность как отсутствие изменений — скучно. Стабильность как отсутствие падений — не противоречит зоопарку.

                                                          берешь качественно сделанную платформу и не лезешь в нее

                                                          Я не представляю, как так можно жить, кроме совсем базовых вещей вроде стандартной библиотеки языка (да и там, на самом деле, лезть надо, чтобы понимать, чем map от unordered_map отличается, просто внутренности привычны почти с детства).
                                                          А вот нужно мне проверить возможность использовать key-value-хранилище на диске, например, и среди прочих кандидатов сразу вылезают LevelDB и RocksDB, которая является продолжением LevelDB. Как можно не почитать, чем они отличаются, что там сделано, какой принцип работы?

                                                          А еще больше я люблю создавать, а не изучать.

                                                          Таки перед тем, как создать что-то адекватное и полезное, стоит узнать, что уже есть.

                                                          А если бы компиляторов Java было не 2, а 20 (как у Питона, например), то усилия всех этих людей были бы распылены на них и каждый в отдельности был бы хуже.

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

                                                          В open-source, где в любой момент код можно беспрепятственно форкнуть, конкуренция — зло.

                                                          Вторя моему предыдущему пункту, в опенсорсе кроме альтернатив «пилить проект» и «форкнуть проект» есть вариант «не пилить ничего». И есть немаленький шанс, что люди, если вы им запретите второй вариант, выберут третий, а не первый.

                                                          Если бы мне внезапно запретили писать мой IM-клиент, я бы не пошёл дописывать Psi или Pidgin, я бы пошёл заниматься матаном.


                                                          1. bigfatbrowncat
                                                            18.09.2015 17:27
                                                            -1

                                                            Почему-то такого опыта у меня нет. Не поделитесь своим? Просто ради интереса.

                                                            Да на здоровье. Взял я как-то Android Libcore. И решил собрать его под Desktop. В нем кучка разных кусков — там и makefile, и autotools и еще кое-что. И всё это надо настроить, пропатчить…

                                                            Ладно, черт с ним. Дорботали напильником, собрали, потом месяц учили его работать под Win32 (читайте выше историю про «b» в fopen), а потом надо было эту всю хрень сцепить с еще одним куском кода, который собирался уже с помощью cmake.

                                                            Хорошо, что там хоть scons нигде не было… Понимаете? Если бы система сборки была одна, то я бы в худшем случае ее одну знал и настраивал, а не скреплял кривыми костылями кучу makefile-ов.

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

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

                                                            Предлагаю простой способ оценки доработанности той или иной технологии. Достаточно узнать, сколько у этой технологии альтернативных реализаций. Чем их меньше, тем технология лучше. Вот, например, вы много видели автомобилей с педалями под рулем или за пяткой? Ни одного. Или, скажем, ружье со спусковым крючком под подбородок…

                                                            А сколько в мире дистрибутивов Linux под десктоп? Их сосчитать не могут — даже те, у которыхбольше одного мейнтейнера. И, кстати, по мере «взросления» дистрибутива Ubuntu, он перетянул на себя внимание большей части Linux-пользователей и разработчиков, поскольку вложить силы во что-то популярное, согаситесь, приятнее.

                                                            Вот у Java был официальный компилятор. IBM он не устроил своей лицензией (и, видимо, имевшимися в тот момент хилыми возможностями), и они написали ECJ. Теперь компилятора два. Между ними есть различия и опытные разработчики их знают. ECJ строже к стандартам, но при этом он умеет делать классы из синтаксически некорректных файлов. А еще он быстрее.

                                                            И хотя Java по популярности обгоняет почти все остальные языки, для нее до сих пор ровно 2 компилятора. И я нигде не слышал, чтобы кто-то пытался сваять третий. Зачем? IDE — как минимум три штуки. А компилера — 2.

                                                            А теперь подсчитайте, сколько на свете компиляторов C/C++ под одну только платформу x86. Не учитывайте устаревшие и заброшенные — берите только актуальные. Пальцев не хватит сосчитать.

                                                            Кстати, JVM достаточно много, но как правило они пишутся по одной из двух причин: оптимизированность под конкретное железо и лицензионные соображения. И обычно тоже максимум 2-3 штуки на платформу. Потому что там всё (относительно) просто и ясно. Что еще улучшать?

                                                            Я не утверждаю, что Java — свет в окошке, а C++ надо выкинуть. Просто степень доработанности Java как инфраструктуры значительно выше, хотя она заметно моложе, чем C++. Ее лучше спроектировали.

                                                            есть вариант «не пилить ничего»

                                                            Нет этого варианта. Дорабатываются open-source проекты в основном по одной и той же практической причине: вам нужна функциональность (исправленная бага), а автор ушел в запой на месяц. А если вы допиливаете столько, что вам начинает казаться, что работаете вы больше него, то вы делаете форк. И никуда вы не денитесь от этого. Можете только закрыть свой проект или оставить открытым (если не GPL). Вот и весь ваш выбор.


                                                            1. 0xd34df00d
                                                              18.09.2015 19:06
                                                              +1

                                                              Да на здоровье.

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

                                                              желание «пилить экзотику» обычно возникает либо у студентов-экспериментаторов

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

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

                                                              Неочевидно, что он адекватен.

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

                                                              Не соглашусь. Вышеприведённый мой опенсорс-проект недоступен под убунтой и, вероятно, в силу разных причин никогда не будет доступен. Нет мейнтейнера (и мне лень и неинтересно его искать), я зачастую использую слишком новый тулчейн (gcc сборку не осиливает, только clang, а как выйдет C++17, так снова ещё проблем добавится), и так далее.

                                                              А компилера — 2.

                                                              Ну, как минимум, IcedTea ещё. Да и, помнится мне, в этой моей генточке аж три разных пакета для dev-java/*-jdk. Далеко от системы сейчас, не посмотрю.

                                                              gcj ещё есть, из сходу приходящего в голову. Не знаю правда, компилятор это ли, виртуальная машина ли, или нечто между.

                                                              А теперь подсчитайте, сколько на свете компиляторов C/C++ под одну только платформу x86. Не учитывайте устаревшие и заброшенные — берите только актуальные. Пальцев не хватит сосчитать.

                                                              Хватило, даже одной руки: clang, gcc, icc, ну и cl.exe ещё, вероятно.

                                                              Думается мне, фортран гарантированно проще, старше и так далее, чем C++, но почему-то компиляторов у него тоже немало.

                                                              А вот для хаскеля, считайте, один ghc есть из мейнстримных, если я правильно понимаю экосистему. И это очень печально, хоть, конечно, компилятор и очень мощный.

                                                              Нет этого варианта.

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


                                                              1. Wedmer
                                                                19.09.2015 01:15

                                                                С++ еще у (Open) Watcom есть. Но там есть проблемы с развитием. А когда то был лучший набор для C/F77.


                                                                1. 0xd34df00d
                                                                  21.09.2015 13:01

                                                                  Ну, там в условии была актуальность и незаброшенность компилятора. Лично для меня актуальность — поддержка C++14 во второй половине 2015 года. Что-то мне подсказывает, что Open Watcom даже про C++11 не очень слышал.


                                                              1. bigfatbrowncat
                                                                19.09.2015 18:28
                                                                -2

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

                                                                Вот тут вы меня заставили улыбнуться. Я уже несколько лет не разрабатывал что-либо не-кроссплатформенное. И выработал-таки себе toolchain, позволяющий писать на C/C++ кроссплатформенные приложения с UI на JVM, при этом не используя не только проприетарные решения в готовом продукте, но и GPL. Только MIT, BSD и Apache.

                                                                Какой смысл писать программу, которая зависит от конкретной платформы или от прихоти держателей Виндоуса или Мака. Так ведь :)

                                                                Вы так говорите, будто это что-то плохое.

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

                                                                Ну, как минимум, IcedTea ещё.

                                                                IcedTea не содержит в себе компилятор. Вот выдержка с оф. сайта:
                                                                The aim of the IcePick [часть IcedTea] project is to allow the language tools (javac, javadoc, javah, javap, apt) from the OpenJDK project to be built separately using any 1.5 compliant Java compiler.

                                                                Вот это — «any 1.5 compliant Java compiler» намекает, что компилятор надо взять где-то снаружи. Хотя я сам не работал с IcedTea, гарантии дать не могу.

                                                                А вот ECJ я разбирал вплоть до исходников. И он как раз и является единственным известным мне компилятором Java, кроме javac от Oracle. Хотя википедия его не приводит, а приводит ныне покойный GCJ, который вы, видимо, считаете полноценным компилятором, которым он не является в силу ограничений интроспекции, несовместимых с мало-мальски продвинутым JVM-кодом. Потому, кстати, и заброшен. ECJ, кстати, — структурная часть Eclipse. Я выше уже писал…

                                                                Хватило, даже одной руки: clang, gcc, icc, ну и cl.exe ещё, вероятно.

                                                                Куча их: вот. Хотя их надо все палочкой потыкать на предмет свежести.

                                                                Вышеприведённый мой опенсорс-проект недоступен под убунтой

                                                                Я сейчас обидную вещь скажу. Хотите популярности вашего продукта — будьте на виду. И сделайте то, чем легко пользоваться везде. Даже специалисты, когда есть выбор, предпочтут из двух конкурирующих технологий (при равных возможностях) ту, которая в их ОС устанавливается одним «apt-get install». Такой уж закон в наших с вами «джунглях». Хотя, он нарушается, если вы ваяете что-то настолько уникальное в смысле предметной области, что ради этого не влом ставить какую-то экзотическую ОСь.

                                                                для хаскеля… из мейнстримных

                                                                Посмотрите вот сюда. Вас же не удивит, например, что для Go и CoffeeScript только один компилятор? Просто уровень популярности Хаскелля таков, что при том уровне требований, которые к нему предъявляются, в основном компиляторе не было найдено ни одного принципиального изъяна.

                                                                В мейнстриме одним единственным компилятором могут похвастаться только Ruby (очень классный язык, учитывая, каких на нем монстров люди ваяют в одиночку) да PHP, «неповторимая глюкавость» которого не позволяет создать альтернативную имплементацию.

                                                                И, кстати, я не считаю, что хаскелль плох. Я не могу так считать, поскольку почти не знаком с ним. Но я знаю, что он — не для мейнстрима. Он, по сути, — язык «для гиков». Разве нет?

                                                                Думается мне, фортран гарантированно проще, старше и так далее, чем C++, но почему-то компиляторов у него тоже немало.

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

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

                                                                Вариант бросить любимое дело и пойти играть в нарды я не рассматриваю здесь. Это был бы явный оффтоп.

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


                                                                1. Wedmer
                                                                  20.09.2015 17:26
                                                                  +1

                                                                  Куча их: вот. Хотя их надо все палочкой потыкать на предмет свежести.

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

                                                                  Я видел. Очень хороший язык для математических задач.


                                                                  1. bigfatbrowncat
                                                                    21.09.2015 02:18

                                                                    Очень хороший язык для математических задач.


                                                                    C# — очень хороший язык для математических задач. Быстро считает, безопасный, легко создать UI при желании и необходимости, есть переопределение операторов и хорошие исключения. Maple — хороший язык для математических задач. Умеет доказывать теоремы и решать уравнения аналитически. MatLab — неплохой язык для работы с большими массивами данных. C++ — приемлимый язык для математических задач, если «умеешь его готовить». Просто потому что исключительно быстрый и позволяет абстрагироваться.

                                                                    Сам я использовал (в большей или меньшей степени) всё это, когда учился, и немного после этого.

                                                                    Среди моих ближайших знакомых есть примерно 10 человек, которые пользуются по крайней мере двумя из перечисленных инструментов (каждый — своими). И среди тех, кто владеет любыми двумя из перечисленных, и еще Фортраном, абсолютно все считают Фортран в лучшем случае неизбежным злом, в худшем — кадавром, которого следует закопать. Из преимуществ — только огромное наследие. Люди написали много матобеспечения на нем и теперь вынуждены развивать то, что работает.

                                                                    Я не верю, что вы найдете хоть одного человека, которому было бы менее сорока лет, который бы умел программировать, который бы знал хотя бы пару из приведенных технологий, и который бы при этом защищал Фортран. Во всяком случае, на факультете ВШОПФ в Нижнем Новгороде, где я учился, таких не было.

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

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

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

                                                                    В любом случае я эту дискуссию продолжать смысла не вижу.


                                                                    1. Wedmer
                                                                      21.09.2015 02:53
                                                                      +1

                                                                      Действительно, смысла нет. У вас мания преследования, и я не желаю ее развивать.


                                                                    1. 0serg
                                                                      21.09.2015 08:22
                                                                      +2

                                                                      Идеальный языки для прототипирования математических задач это, имхо, Python :). Шарп и плюсы проигрывают ему со свистом в обилии легкодоступных инструментов и удобстве их использования.


                                                                      1. 0xd34df00d
                                                                        21.09.2015 13:20

                                                                        Не могу с вами согласиться. Вероятно, потому, что патологически не переношу динамически типизированные языки для чего-либо, кроме одноразовых скриптов на 20 строк.

                                                                        Лучше уж плюсы и хаскель, для моих задач даже прототипировать вполне удобно, с инструментами проблем нет. Ну или R ещё, тоже получше питона, специализированная такая штука.


                                                                        1. 0serg
                                                                          21.09.2015 15:52

                                                                          Ну, я тоже не переношу динамически типизированные языки и был сильно против питона пока не попробовал :). Прямо в консоли половину дел можно сделать. А раньше думал — зачем питону этот режим консольного интерпретатора? Оказывается в массе случаев — крайне удобно. Есть такая софтика Spyder — по сути сборка питона с простенькой IDE и расширенным набором библиотек из коробки, и там очень неплохо эта тема обыграна. На большие проекты естественно отмасштабировать будет трудно, но до 10k строчек работает вполне комфортно и для прототипирования — самое оно.


                                                                          1. bigfatbrowncat
                                                                            21.09.2015 16:05
                                                                            -1

                                                                            Если вы можете удержать всю логику программы в голове одновременно, то всё равно, на чем ее писать и как. Где синтаксис привлекательнее, на том и пишите.

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


                                                                            1. 0serg
                                                                              21.09.2015 16:28
                                                                              +1

                                                                              Я же написал — «для прототипирования».
                                                                              Нормальные задачи естественно требуют подумать над моделью и архитектурой.
                                                                              Шарп тут кстати между сциллой и харибдой оказывается — для прототипирования удобнее питон, для нормальной реализации — плюсы. А шарп — ни рыба и ни мясо.


                                                                      1. bigfatbrowncat
                                                                        21.09.2015 16:07
                                                                        -2

                                                                        Про легкодостпные инструменты, я бы поспорил. Я сравнивал PyCharm с Eclipse CDT и CDT была намного мощнее. Хотя, конечно, Python надо сравнивать с C# и Java, а не с C++. Разная весовая категория…


                                                                        1. 0serg
                                                                          21.09.2015 16:38
                                                                          +2

                                                                          Мощность и простота использования — разные вещи. Мощная IDE с богатыми возможностями для рефакторинга, юнит тестирования и проектов на десятки тысяч файлов для прототипа мне нужна как собаке пятая нога. А вот удобный и простой рантайм где все правится на лету, богатейшие по функционалу и подключаемые в одну команду библиотеки, плюс приличное количество примеров использования в Сети оказываются очень к месту.


                                                                1. 0xd34df00d
                                                                  21.09.2015 13:18
                                                                  -1

                                                                  Какой смысл писать программу, которая зависит от конкретной платформы или от прихоти держателей Виндоуса или Мака. Так ведь :)

                                                                  Я пишу под более-менее POSIX-совместимые платформы, где есть gcc или clang. Лучше clang, да. Линуксы, FreeBSD, даже OS X.

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

                                                                  Хотя формально моя опенсорс-поделка кроссплатформенна (с точностью до поддержки платформ Qt и boost'ом), например, просто есть проблемы с достаточно совместимыми компиляторами :)
                                                                  Да и подавляющая часть рабочего кода тоже кроссплатформенна, с точностью до пары системоспецифичных вызовов, призванных тонко настроить пару узких мест.

                                                                  Просто я не рассматриваю всерьез их вклад в развитие индустрии.

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

                                                                  Хотя я сам не работал с IcedTea, гарантии дать не могу.

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

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

                                                                  Ну, тут уж я ничего не знаю, ибо не работал с ним. Однако, как видите, он всё равно есть, зачем-то написан, тянется с новыми релизами gcc, и так далее. И я, был бы неофитом, запутался бы, и пришлось разбираться, что там да как. Так что всё не так уж просто, как вы сначала писали про два компилятора :)

                                                                  Куча их: вот. Хотя их надо все палочкой потыкать на предмет свежести.

                                                                  Это не куча, это, простите, хрень какая-то. Приводить в этом списке Dev-Cpp, который по сути IDE для Windows поверх gcc, это несерьёзно. Дальше даже смотреть неохота.

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

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

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

                                                                  Gentoo не такая уж и экзотическая. И она не ради проекта, просто так получилось, что мне под ней вообще удобнее.

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

                                                                  Да не в изъянах даже дело, а в экспериментах. Альтернативные компиляторы нужны не только для того, чтобы, собственно, предоставить альтернативную реализацию языка, а ещё и для того, чтобы поиграться с некоторыми экспериментальными возможностями. Не знаю, расширения системы типов, автоматическое распараллеливание на GPU, какие-то другие ништяки для параллелизма, да мало ли. А это всё, если и делается, зачастую пихается в бедный несчастный ghc, который не резиновый всё-таки. Мне, с одной стороны, это приятно, потому что тем фичастей компилятор доступен, с другой — как-то интуитивно это не нравится.

                                                                  Вы, наверное, не видели фортран.

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

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

                                                                  Вариант бросить любимое дело и пойти играть в нарды я не рассматриваю здесь. Это был бы явный оффтоп.

                                                                  Но это, тем не менее, вполне себе вариант, и не рассматривать его было бы ошибочно.


                                                          1. bigfatbrowncat
                                                            18.09.2015 17:40
                                                            -1

                                                            Пардон, не дочитал:

                                                            Если бы мне внезапно запретили писать мой IM-клиент, я бы не пошёл дописывать Psi или Pidgin, я бы пошёл заниматься матаном.

                                                            А задайтесь вопросом, откуда у вас вообще возникло желание написать свой IM «с блекджеком...» У меня, кстати, такое желание тоже периодически возникает! И я знаю, почему. Точно знаю.

                                                            Причина в том, что имеющиеся меня не устраивают. Они по большинству своему ненадежны, некроссплатформенны, коррумпированны или платны. Вот и притягивает эта задача девелоперов как огонь мотылька. Чем большее число пользователей не устраивает имеющаяся ситуация — тем больше «пильщиков».


                                                            1. 0xd34df00d
                                                              18.09.2015 18:55
                                                              +1

                                                              А у меня не так. Мне просто нравится писать код.


                                                              1. bigfatbrowncat
                                                                19.09.2015 18:30

                                                                Мне тоже нравится. Вам всё равно, какой код писать? Мне — нет. Я пишу тот код, который мне интересно писать. И полагал, что вы поступаете аналогично.

                                                                Я же не изучал «фокус-группу». И маркетинговые исследования не проводил. Просто я осознаю (предполагаю), по какой причине мне хочется того или иного. Стараюсь понимать причину своих устремлений. Это полезно.


                                                                1. 0xd34df00d
                                                                  21.09.2015 13:21

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


                                              1. withkittens
                                                16.09.2015 11:15
                                                +1

                                                Chaos_Optima,

                                                С точки зрения проектирования Listener в Java и event в C# — совершенно одно и то же
                                                Ну вообщето далеко не одно и тоже
                                                Извините, что вклиниваюсь в ваш жаркий спор, но таки мне самому интересно.
                                                Listener в яве требует наследования от интерфейса.
                                                Ок.
                                                в С# же и в С++ этого можно избежать.
                                                Ок.

                                                И таки в чём принципиальная разница? И там, и сям паттерн Listener. В Java он многословный, а чтобы подписать несколько колбэков, нужно сгородить собственный адаптер (каюсь, могу не знать, есть ли в стандартной библиотеке что-то уже готовое). В C# паттерн встроен в язык, оттого он и проще.

                                                Оппонент вам пишет, что в одном и другом случае, это механизм колбэков — вызов чего-то там в ответ на произошедшее событие. Реализация — разная, смысл — один.

                                                По-моему, вы стараетесь к чему-нибудь прицепиться и придраться, попутно принижая оппонента — «вы не знаете то, вы не знаете сё». Большой Толстый Коричневый Кот выражает своё мнение, вы можете быть с ним не согласны, но вы переходите на личности, а Кот — нет. Так дискуссия продолжаться не должна.

                                                Я не его адвокат, но я так вижу как сторонний наблюдатель.


                                                1. Chaos_Optima
                                                  16.09.2015 11:30

                                                  И таки в чём принципиальная разница?

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


                                                  1. bigfatbrowncat
                                                    16.09.2015 22:12
                                                    -1

                                                    Критика изначально была в том, что на С++ не нужно писать как на яве.

                                                    Покажите мне, где я вам сказал, что в C++ НАДО писать как в Java. Я такого не говорил ни разу.

                                                    Я говорил, что C++ на высоком уровне принимает парадигмы и вид, очень сильно напоминающий Java, только без кучи ее плюшек и защиты. Понимаете? Универсальность влечет за собой понижение комфорта исвользования в каждом конкретном случае. Молоток с одной стороны, отвертка с другой, перочинный нож вместо рукоятки. Удобно пользоваться?

                                                    Вы просто слишком буквально меня поняли.


                                                1. bigfatbrowncat
                                                  16.09.2015 22:10
                                                  -1

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

                                                  Кстати, недавно увидел классный язык, почти всем мне нравящийся (кроме мелочей). Он на JVM, то есть Java-совместим в нем есть свойства, переопределяемые операторы, константная корректность… Жаль, что там отказались от checked exceptions (это — одна из мощнейших фич Java, по-моему). Kotlin называется. Видели?


                                                  1. withkittens
                                                    16.09.2015 23:28
                                                    -1

                                                    Если вопрос не мне, то считайте что это ответ в пустоту :)

                                                    Слышал про Котлин и про Скалу. Но не имел дела с ними.
                                                    Взять тот же Андроид — надеюсь, на них можно под него писать, поскольку голая Java (а на андроид она ещё и без лямбд!) лично у меня вызывает мгновенное оторжение из-за многословности и топорности. Listener — хороший тому пример.

                                                    P.S. Си-шарпщик.


                                                    1. bigfatbrowncat
                                                      17.09.2015 00:37

                                                      Котлин — наверняка поддерживается. Так как сейчас Гуглы взяли в основу Android Studio платформу IntelliJ, а именно эти ребята его придумали, думаю, проблем нет. Там же только компиляция, по сути, отличается. Хотя API рассчитана на Java…


                                        1. Wedmer
                                          16.09.2015 00:02
                                          +1

                                          Из своего опыта я приводил уже пример где то ближе к стволу дерева.

                                          Я просто приводил общеизвестные факты.

                                          Как раз популярность C++ и кроется в его универсальности.

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

                                          А если серьезно, то красив хорошо спроектированный код

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


                                          1. bigfatbrowncat
                                            16.09.2015 03:42
                                            -2

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


                                            Ну слава макаронному монстру, хоть в чем-то договорились!

                                            C++ несовместим с C в смысле своих возможностей. И необходимости писать extern «C», чтобы избежать name mangling-а. И еще пара мелочей… Ну и что? Всё равно когда вам нужен очень-очень эффективный код, вы перестанете использовать vector и возьметесь за старый добрый int[]. Возможно, вы вместо malloc, напишете new. Не исключаю, что в суперэффективном коде у вас пару раз проскочит какой-то класс. Но в основном это будет код на Си. Потому что высокоуровневые абстракции едят производительность. Вы не можете даже полиморфизм толком использовать, потому что vtable — это лишний резолв указателя при каждом вызове функции. Всё, что останется от C++ — это статические касты… и C. Вот такой нижний уровень.

                                            А на верхнем уровне вы упретесь в необходимость либо линковать код в один бинарь, либо бить его на кучу динамических библиотек. Компиляция долгая… ОЧЕНЬ долгая (привет Джаве, где строятся отдельные class-файлы в проекте любого масштаба). Ошибки связывания, необходимость указывать библиотеки глупому линковщику в правильном порядке. Сборочная система CMake хороша, но ее придется учить. Старый-добрый make требует написать целую программу, которая соберет вашу программу. А про autotools я и говорить не хочу…

                                            Я честно не знаю, о чем думал человек, придумавший разделение на .h и .c/.cpp файлы в виде простого включения одних в другие. Даже в древнем Turbo Pascal-е линковщик был умнее.

                                            Эти недостатки общие для С и C++, но на C все-таки редко пишут проекты, содержащие 1000 файлов. (Пишут конечно, но это — вообще ад кромешный). А С++ на это всерьез претендует — так почему бы хоть сборочную инфраструктуру не включить в стандарт языка, как это сделано в Java и C#?

                                            О такой мелочи как аналог JavaDoc я и говорить боюсь…

                                            Мало аргументов?

                                            Теперь я спрашиваю: представьте, что лично вы, в одиночку, собираетесь создать серьезный проект с интересной математикой и сложной бизнес-логикой. Скажите мне, неужели вы станете писать управляющий код на C++? Или, всё же, ограничитесь математическим backend-ом, а контроллеры и UI напишите на чем-то более приемлемом?

                                            Может быть, я что-то серьезно не понимаю…


                                            1. Chaos_Optima
                                              16.09.2015 04:38
                                              +1

                                              сё равно когда вам нужен очень-очень эффективный код, вы перестанете использовать vector и возьметесь за старый добрый int[].

                                              Эм… зачем, когда есть array. Ну и да внутри vector и int* по большей часть одинаковые.
                                              Вы не можете даже полиморфизм толком использовать, потому что vtable — это лишний резолв указателя при каждом вызове функции.
                                              Лол, как будто в C# и Java это делается по другому)). Ну и да современные компиляторы, когда могут точно определить класс не прыгают по vtbl.
                                              Всё, что останется от C++ — это статические касты… и C. Вот такой нижний уровень.

                                              А ещё шаблоны, ссылки, raii, инкапсуляция, лямбды, constexpr, auto, decltype и куча других приятных мелочей.
                                              Ошибки связывания, необходимость указывать библиотеки глупому линковщику в правильном порядке. Сборочная система CMake хороша, но ее придется учить.

                                              И правда IDE то у нас нет, приходится всё ручками в консоле компилить, и даже CLion не умет правильно cmake генерировать.
                                              О такой мелочи как аналог JavaDoc я и говорить боюсь…

                                              Действительно, ведь так мало средств для документации С++, даже доксигена нет.

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


                                              1. bigfatbrowncat
                                                16.09.2015 10:53
                                                -1

                                                Лол, как будто в C# и Java это делается по другому)).

                                                Я не говорил, что писать в этом случае надо на Java. Я считаю, что в этом случае вполне можно писать на Си.

                                                И правда IDE то у нас нет

                                                Есть, конечно, но имеющийся большой проект, например, вы в IDE замучаетесь засовывать. Люди изобрели столько разных сборочных систем для C++, что со всем этим зоопарком просто не разобраться. В данном случае в первую очередь надо думать о legacy, конечно. В вашем собственном проекте вы найдете приемлимую настройку (хотя, привязывать проект к одной IDE — это не комильфо).

                                                так мало средств для документации С++, даже доксигена нет

                                                Я, честно говоря, не в курсе — а есть IDE, которая из комментариев Doxygen делает контекстную подсказку при вводе кода?

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

                                                было бы неплохо хотя бы 5 минут посидеть и погуглить эти вопросы

                                                Единственное в чём вы оказались правы так это в отсутствии модульности в С++

                                                Разница между мной и вами в том, что я просто имею более высокую планку требований к инструменту. Вас устраивает поддержка CMake в CLion и вы считаете, что это удобно. Я считаю, что должен либо знать сборочную систему досконально сам, либо она должна быть одна, стандартная и поддерживаться ВЕЗДЕ. А желательно — и то, и другое разом. Я уже 13 лет занимаюсь программированием профессионально и за это время мне порядком надоело иметь дело с недоработанными и неудобными инструментами. Даже если они мощные. Только и всего. К примеру, когда я знаю, что мой проект собирается только в одной конкретной IDE, только под одной ОС или я не знаю, как он собирается, я этого не терплю.


                                                1. Chaos_Optima
                                                  16.09.2015 11:23

                                                  Я не говорил, что писать в этом случае надо на Java. Я считаю, что в этом случае вполне можно писать на Си.

                                                  Эм… то есть когда нужен полиморфизм, нужно использовать С? 0_о не думаю что вы могли бы дискредитировать себя сильнее чем сейчас.
                                                  Есть, конечно, но имеющийся большой проект, например, вы в IDE замучаетесь засовывать.

                                                  0_0 wat? Я ошибся, вы всё таки умудрились дискредитировать себя ещё сильнее.
                                                  Я, честно говоря, не в курсе

                                                  Поэтому я вам и советовал погуглить прежде чем чушь писать
                                                  а есть IDE, которая из комментариев Doxygen делает контекстную подсказку при вводе кода?

                                                  Да Visual Studio.
                                                  Просто он не является частью стандарта — это лишь костыль

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

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


                                                1. 0xd34df00d
                                                  16.09.2015 14:26
                                                  +2

                                                  есть IDE, которая из комментариев Doxygen делает контекстную подсказку при вводе кода?

                                                  kdevelop.


                                            1. Wedmer
                                              16.09.2015 05:20
                                              +2

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

                                              Я люблю Doxygen. Есть ещё варианты.

                                              Проблем с Autotools и make тоже не вижу. Ещё есть qmake, b2. Вы лучше подумайте, чем и как собирается java runtime.

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

                                              Не вижу беды в 1000 файлах, если оно так нужно. Ведь для каждого правила сборки писать не надо.

                                              Извините за несистемные ответы, но с мобильного клиента писать не очень удобно.


                                              1. bigfatbrowncat
                                                16.09.2015 11:02
                                                -2

                                                у нас на нижнем уровне нужен высокий уровень абстракции

                                                Дайте конкретный пример одного неразделимого куска кода, где требуется одновременно ООП, высокий уровень абстракции и максимальная производительность.

                                                Я люблю Doxygen. Есть ещё варианты.
                                                Проблем с Autotools и make тоже не вижу. Ещё есть qmake, b2.


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

                                                Вы лучше подумайте, чем и как собирается java runtime.

                                                Подумал. И даже собирал OpenJDK. Жутко он собирается. Сложно, разношерстно и долго. Но, к счастью, человек, пишущий на Java, а не саму Джаву, лишен необходимости заниматься подобными вещами.

                                                А вот Java-код собирается всегда одинаково. Класс файл на один исходник. Файлы лежат по структуре, совпадающей с именами пакетов. Сборка осуществляется путем «компилятор, возьми все эти Java-файлы и все эти jar-библиотеки и сделай мне .class вот сюда».

                                                Тут не с чем разбираться и не в чем путаться. Я могу взять любой Java-проект любой сложности и, если у него нет нативных расширений, собрать его буквально одной командой. И, к счастью, разработчикам обычно не приходит в голову изобрести еще одну САМУЮЛУЧШУЮ систему сборки для Java.

                                                Кстати в обоих языках можно жить без заголовочников (кроме системных

                                                Это, простите, как? Инклюдить один сырец из другого? Быстрая у вас, однако, сборка будет…

                                                Не вижу беды в 1000 файлах, если оно так нужно

                                                И я не вижу. Но этой кучей должно быть легко управлять.


                                                1. Wedmer
                                                  16.09.2015 13:46
                                                  +2

                                                  Дайте конкретный пример одного неразделимого куска кода, где требуется одновременно ООП, высокий уровень абстракции и максимальная производительность.

                                                  Тот самый проект, про который я писал ближе к стволу дерева. К сожалению, код я вам показать не могу по понятным причинам. Конечно все там можно было написать на голом C, с применением ООП, но проект изначально разрабатывался на C++/boost, да и одним из основных критериев были сжатые сроки.

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

                                                  И, к счастью, разработчикам обычно не приходит в голову изобрести еще одну САМУЮЛУЧШУЮ систему сборки для Java.

                                                  Вы забываете, что Java компилируется в платформонезависимый байткод и там только Java. В простых проектах на C или C++ тоже достаточно небольшого Makefile, который вам все соберет на любой платформе одной командой make. Но если начинает пахнуть такими вещами как «Платформозависимый код» или «кросскомпиляция» и кучей зависимостей, то Makefile уже не позволяет все это упростить. Именно поэтому были сделаны Autotools, которые сгенерят configure и некоторые шаблоны к нему, удовлетворяющие среде сборки, а при запуске configure вы уже настроите все под целевую платформу.
                                                  Конечно, если зависимостей не очень много и проект не очень крупный, то всё равно можно обойтись и одним Makefile, который будет настраиваться через переменные окружения. Да, приходится платить временем для создания конфигурации управления зависимостями, но производительность конечного продукта этого стоит. Лично я пользуюсь qmake. В заговорили о стандартах? Извините, это универсальные инструменты, которые могут собрать проект, если он написан на всех возможных языках сразу. Если вдруг для C/C++ появится стандартный для всех реализаций инструмент, то эти системы все равно останутся и будут использовать этот новый инструмент.

                                                  Это, простите, как? Инклюдить один сырец из другого? Быстрая у вас, однако, сборка будет…
                                                  Это плохая техника, но она применяется ( привет средам типа IAR ). Для компиляции указываются только конечные потребители кода.

                                                  Но этой кучей должно быть легко управлять

                                                  Не сложнее, чем такой же кучей на Java.


                                                  1. bigfatbrowncat
                                                    16.09.2015 22:26
                                                    -2

                                                    Вы забываете, что Java компилируется в платформонезависимый байткод и там только Java.

                                                    Смотрим в исходник IntelliJ IDEA. Там есть Java, Groovy и Kotlin. А еще куча всякой интересной модульности. И всё это собирается прямо из той же самой IDE. Хотя чести ради надо сказать, что из консоли для сборки нужен gradle. Но gradle, в отличие от большинства сборочных систем для C/C++, устроет так: пишешь «вот тут у меня Java, тут Kotlin, тут ресурсы, результат положи, пожалуйста, сюда и запакуй в jar с вот таким именем». И на этом вся конфигурация заканчивается.

                                                    Eclipse, правда, собирается с помощью чуть более сложного Maven-а, но он — уже сборочная система, которая считается Enterprise-решением. Им пользуются матёрые джависты в проектах, для которых используют монстров типа Spring Framework.

                                                    Кстати, полный объем исходных кодов Eclipse Platform составляет примерно 2 гигабайта. Это именно исходники. Результат (со всеми установленными плагинами) будет мегов четыреста. И этот монстр довольно легко правится, отлаживается и дорабатывается. Такие вот масштабы.


                                                  1. bigfatbrowncat
                                                    16.09.2015 22:27

                                                    Думаю, спор надо прекращать.

                                                    Я весьма посредственно знаю C++ на уровне крупных Enterprise-проектов.

                                                    Вы, по всей видимости, практически не знаете Java.

                                                    Каждый любит то, что знает (или, наоборот, знает то, что любит)


                                            1. Wedmer
                                              16.09.2015 05:37
                                              +2

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


                                              1. bigfatbrowncat
                                                16.09.2015 12:03
                                                -2

                                                C++ я действительно знаю поверхностно. На уровне стандарта 98 года. Qt, Boost не знаю, да. Первый слишком проприетарен, чтобы мне хотелось его использовать для себя, а по работе не приходилось. Второй слишком заморочен.
                                                Учился C++ на работе я, дорабатывая ОС Symbian.

                                                А вот Си знаю вдоль и поперек. Хотя в проектах на «Си с ООП», слава богу, не участвовал уже 4 года. Если быть совсем честным, то обычно я «скоростной» код пишу на C++, ограничивась функциональной парадигмой. То есть использую new/delete вместо malloc/free. Контейнеры использую по минимуму.


                                                1. 0xd34df00d
                                                  16.09.2015 14:28
                                                  +1

                                                  Второй слишком заморочен.

                                                  Ну тут просто нечем крыть, на самом деле.

                                                  ограничивась функциональной парадигмой

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


                                                  1. bigfatbrowncat
                                                    16.09.2015 22:15
                                                    -1

                                                    Императивная парадигма от функциональной отличается отсутствием глобального состояния. Пишите «чистые» функции и будет вам счастье. Что я упустил?


                                                    1. 0xd34df00d
                                                      17.09.2015 16:16

                                                      И локального тоже. Никаких вам static'ов и никаких printf/scanf в чистых функциях. Даже для логгирования (хаскелевский читерский Debug.Trace не в счёт).

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

                                                      А ещё лично для меня ФП немыслимо без хорошей, развитой и мощной системы типов.


                                                      1. bigfatbrowncat
                                                        18.09.2015 13:02
                                                        -1

                                                        И локального тоже.

                                                        Я там, выше по дискуссии, писал, что ФП — вещь тяжело усваиваемая. Я, конечно, как человек, плохо его знающий, не имею права его критиковать, но всё же…

                                                        Я точно знаю, что такое состояние системы и откуда оно берется. Философская концепция, лежащая в основе ООП, мне понятна и я, при желании, могу объяснить ее 6-летнему ребенку.

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

                                                        (к слову, если логгер передавать среди аргументов функции, то логгирование возможно и в ФП-подходе, так? Только, правда, я с детства приучал себя передавать в функции как можно меньше параметров)

                                                        без хорошей, развитой и мощной системы типов

                                                        То есть без классов? Или вы про какие типы говорите? Что-то я запутался…


                                                        1. 0xd34df00d
                                                          18.09.2015 16:35
                                                          +2

                                                          Я там, выше по дискуссии, писал, что ФП — вещь тяжело усваиваемая.

                                                          Я так и не понял, чего там тяжело усваиваемого, ну да ладно. Впрочем, когда я тот же Хаскель в своё время в первый раз ковырял, да, мозги вполне себе ощутимо скрипели. Но какие же ментальные оргазмы этот скрип давал!

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

                                                          Всё — функция в математическом смысле слова.

                                                          к слову, если логгер передавать среди аргументов функции, то логгирование возможно и в ФП-подходе, так?

                                                          Да, почти так. Если сильно упрощать, логгером может быть просто список строк, который вы берёте на вход и в который что-то там дописываете.

                                                          То есть без классов?

                                                          Да, без классов :) Только не тех, что в C++ или C#, а тех, что классы типов.

                                                          В общем, лучше ссылку дам на замечательную книгу по теме: newstar.rinet.ru/~goga/tapl/tapl.pdf


                                                  1. Mrrl
                                                    16.09.2015 22:23

                                                    А может быть, продецурную вместо объектно-ориентированной?


                                                    1. 0xd34df00d
                                                      17.09.2015 16:14

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


                                            1. 0xd34df00d
                                              16.09.2015 14:24
                                              +1

                                              Всё равно когда вам нужен очень-очень эффективный код, вы перестанете использовать vector и возьметесь за старый добрый int[].

                                              Зачем? Если я заранее знаю размер, то vector::reserve() меня спасёт.

                                              Вы не можете даже полиморфизм толком использовать, потому что vtable — это лишний резолв указателя при каждом вызове функции.

                                              Во-первых, не всегда, современные компиляторы хорошо делают виртуализацию, особенно для final-классов и функций.
                                              Во-вторых, плюсы vtable'ами не ограничиваются. Останутся лямбды, темплейты, обычные классы для RAII, семантика перемещений… Да много чего останется, на самом деле.

                                              Сборочная система CMake хороша, но ее придется учить.

                                              Инструменты вообще полезно учить.

                                              Или, всё же, ограничитесь математическим backend-ом, а контроллеры и UI напишите на чем-то более приемлемом?

                                              Лично я напишу либо всё на плюсах, либо всё на хаскеле (возможно, с биндингами к каким-нибудь сишным blas'ам/lapack'ам через какой-нибудь hmatrix), а от UI постараюсь держаться подальше.


                                        1. 0xd34df00d
                                          16.09.2015 14:11
                                          +2

                                          Вот на низком уровне мне нужно сделать файлу mmap(), гонять потом memchr для поиска разделителя и оборачивать токены в boost::string_ref (эх, где ж мои string views из C++17!). Это уже Си или ещё нет?

                                          Что для вас «превращение в Си»?


                                    1. 0xd34df00d
                                      16.09.2015 14:09
                                      +2

                                      Потому что это, по моему мнению, — бестолковое занятие, которое отнимает силы и время и не содержит в себе ни капли творчества.

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


                        1. bigfatbrowncat
                          15.09.2015 16:00
                          -2

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

                          Вот вам пример сложной программы, например: en.wikipedia.org/wiki/NWChem
                          Моделирует квантовые состояния и переходы в атомах. В частности. И много чего еще другого.

                          Думаете, приведете в пример UI сопоставимый по сложности?

                          А игры, конечно, бывают разные. Бывают и очень непростые алгоритмы, но они очень редки.


                          1. Chaos_Optima
                            15.09.2015 16:30
                            +2

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

                            Думаете, приведете в пример UI сопоставимый по сложности?

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

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

                            Конечно в плане математики они сильно уступают NWChem, но это не делает их простыми.


                            1. bigfatbrowncat
                              15.09.2015 16:41
                              -3

                              Давайте не ударяться в софистику. Движок игры — это не UI. UI — это то, во что тыкают кнопками и мышкой. Иногда еще gamepad туда же.

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

                              Но, еще раз: UI среди них нет.

                              Я читал код Android Framework и изучал внутреннее устройство виджетов и всего с ними связанного. Это — простой код. Он полон нюансов и мелких решений и оптимизаций, которые делают его непростым в плане развития, но ничего фундаментально сложного там нет.

                              Я разбирался во фреймворке SWT и много внутри видел. В частности, сделал статическую сборку для встраивания в исполняемые файлы. И там тоже нет ничего сложного.

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


                              1. Chaos_Optima
                                15.09.2015 16:56

                                Я и не ударяюсь в софистику, это вы написали что игры это просто.

                                Но, еще раз: UI среди них нет.

                                Ещё раз повторяю, браузеры.
                                Что касается браузеров, то там вся сложность — оптимизация.

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


                                1. bigfatbrowncat
                                  15.09.2015 17:30
                                  -2

                                  Приведите мне пример браузера, написанного на Хаскелле.

                                  Приведите мне пример игры AAA-класса (по вашему же определению), написанной на Хаскелле.

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

                                  Когда я говорил о простых задачах, вы прекрасно поняли, что я имею в виду. Я имел в виду задачи, решаемые фреймворком типа Qt и игровыми движками типа Unity.

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


                                  1. Chaos_Optima
                                    15.09.2015 17:55
                                    +1

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

                                    Нет, я про хаскелль вообще не говорил, я лишь указал вам что вы неправы, говоря что UI и игры это простые задачи.
                                    С++ как раз создан для решения сложных задач по типу браузеров и игр.
                                    Я имел в виду задачи, решаемые фреймворком типа Qt и игровыми движками типа Unity.
                                    Дык и я говорю о том же, фреймворки типа Qt и дивижки типа юнити это не простые задачи.
                                    Изначально я утверждал, что C++ плохо справляется с решением задач в той области, для которой он считается (своими же адептами!) наиболее пригодным.
                                    Я именно это и оспариваю )).


                                    1. Wedmer
                                      15.09.2015 17:57
                                      +2

                                      Есть подозрение, что спорить бесполезно.


                1. bigfatbrowncat
                  14.09.2015 13:31

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

                  Я сам в институте почти что боготворил C++ за его красоту и целостность. Раздражение пришло позже, когда я сперва научился писать сложные (больше 5000 строк кода) программы, а потом увидел C# и осознал, сколько усилий в C++ приходится тратить лишь на то, чтобы программа не разваливалась на старте. При этом выигрыш по производительности, которым все адепты размахивают как флагом, составляет считанные проценты, а там, где он существеннее, есть JNI (в Java) и PInvoke (в C#). И программа, написанная на «коктейле» будет работать так же быстро. Только она будет надежнее. И вы ее быстрее сделаете.


                  1. 0xd34df00d
                    14.09.2015 13:42
                    +2

                    Для обучения C++ сложнее, вероятно, чем C#.

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

                    В том же C# тоже наверняка есть какая-нибудь лажа. Да что там далеко ходить, буквально на днях на глаза попалось это вот. Кое-что там — весьма откровенные придирки, ИМХО (вроде претензций к оператору инкремента), но кое-что ИМХО шедеврально, вроде пункта 1.

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


                    1. bigfatbrowncat
                      14.09.2015 19:17
                      -1

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

                      Наделали бы несомненно. Но поймали бы их в два счета с помощью имеющегося отладчика и отличных стектрейсов.

                      Проблема не в сложности C++! Я про сложность не писал ничего. Проблема в том, что он весь состоит из «дырявых» абстракций. Чтобы написать нормальный код на C++ надо сперва самому придумать и выбрать некое подмножество его возможностей, которым вы сами себя ограничите и запомнить набор правил. А потом железно этим правилам следовать. В противном случае у вас будет ошибка в месте кода А, а программа свалится через 10 минут в месте кода Б. И идите — разыскивайте, где вы там испортили что…


                      1. 0xd34df00d
                        14.09.2015 19:24

                        Но поймали бы их в два счета с помощью имеющегося отладчика и отличных стектрейсов.

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

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

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

                        И идите — разыскивайте, где вы там испортили что…

                        В таких случаях я добавляю во флаги сборки -fsanitize=address.


                        1. lair
                          14.09.2015 19:26
                          +1

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

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

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


                          1. 0xd34df00d
                            16.09.2015 14:31

                            И даже в приведенном вам списке далеко не все такие.

                            Про это я сразу и сказал.

                            А ошибки с копированием объектов и вообще памятью — похуже.

                            Если взять за правило, например, дебажные сборки собирать с asan'ом, то так же.

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


                      1. Chaos_Optima
                        14.09.2015 20:46

                        Интересно узнать каков ваш опыт работы с С++? Просто за те 6 лет что я на нём работаю. у меня никогда небыло трудностей что вы говорите, даже когда только начал. Всегда выбирал методы нужные для решения задачи исходя из задачи, основная идея языка это е использовать того что ненужно, а по вашим словам получается какбудто есть всего 2 возможности, либо используй всё либо используй ничего. Оч странно выглядит.


                  1. 0serg
                    14.09.2015 14:45
                    +1

                    Что-то я не видел ни программ C++ где нужно прикладывать массу усилий чтобы все «не развалилось при старте», ни программ на C# где не требовалось бы писать кучу еще более дурацкого boileplate. Весьма показательным, имхо, моментом является то что у нас в проекте когда такие же «светлые головы» решили что вычислительное ядро будет на плюсах, а бизнес-логика и UI — на шарпе, то первым (!) что было сделано на шарпе стало использование какого-то дурацкого IOC фреймворка, который спрятал половину инициализации в непрозрачный third-party бинарник. Затем чуть ли не полгода эти «спецы в C#» делали несложный интерфейс с одним окном для рендеринга 3d-сцены, одним меню и несколькими кнопками в этом окне, т.е. вещь настолько тривиальную, что дальше уже некуда. Дальше были танцы с бубном чтобы подключить к этому окну third-party рендерер. Дальше, естественно, возникли обширные проблемы в общении между плюсовым кодом и шарповым, так что несчастный message box пилили, наверное, месяц. Далее я заметил что добавление банальнейшего элемента в меню требует ручной правки то ли шести то ли восьми (!) файлов. Шаг влево, шаг вправо — и где-то отваливаются ресурсы, из-за чего message-box ы с сообщением об ошибке выглядят абсолютно пустыми. Как сделать банальное диалоговое окно — непонятно вообще, такое впечатление что нужно править вручную машиночитаемую разметку — привет XAML. Слава Богу, что пока что нам это не нужно и это создает со стороны впечатление что UI успешно сделан и прекрасно работает, но я-то знаю, что диалоговые окна которые раньше мог спокойно добавить любой разработчик, сейчас может добавлять только один или два человека в команде, которые шарповый код писали, потому как больше в этом коде сходу разобраться не может никто. В общем, пиздец как он есть. А ведь могли бы сделать на Qt — там все а) работает с полпинка, б) легко читается и правится, в) не требует геморроя с взаимодействием между кодом на шарпе и плюсах. Pinvoke — это хорошо когда надо одну-две функции дергать, а когда на плюсах «живут» не отдельные «оракулы» которые C# дергает в синхронных вызовах а полноценные непрерывно обрабатывающие данные потоки асинхронно от C#, то пробросить (и отладить) нормальный интерфейс довольно непросто.

                    Это я конечно не к тому чтобы C# плох и виноват во всех этих бедах. Понятно что там программисты на шарповой стороне были очень посредственными и накосячили с архитектурой. Но, блин, вся ж идея с шарпом, по идее, в том что там накосячить должно быть сложно, а сделать правильное решение — легко и просто. И вот этой простоты я что-то абсолютно не наблюдаю. Примерно такую же хрень мог бы нагородить в UI-е любой школьник пишущий на плюсах для MFC. Вероятно шарп это шаг вперед по сравнению с MFC (ибо последний — это вообще запредельное убожество), но по сравнению с Qt, по ощущениям, это два шага назад.

                    Здесь правда следует сделать поправку на то что плюсовые программы я писал сам, тогда как шарповые смотрел сделанные другими.


                    1. lair
                      14.09.2015 15:01

                      первым (!) что было сделано на шарпе стало использование какого-то дурацкого IOC фреймворка, который спрятал половину инициализации в непрозрачный third-party бинарник.

                      Имя, сестра, имя!

                      (но вообще, конечно, плохая архитектура — она на любом языке плохая архитектура, от нее не защитишься)


                      1. 0serg
                        14.09.2015 16:06
                        +2

                        Caliburn.Micro и какую-то хрень LogoFX, но по сути это совершенно неважно.
                        Моя позиция в том что с хорошей архитектурой и на плюсах и на шарпе будет написан примерно одинаковый код за примерно одинаковое время. У каждого языка будут свои плюшки и минусы (шарп — лучше стандартная библиотека, тогда как к плюсам надо еще подключать что-то, плюсы — быстро работают из коробки), но общая разница будет весьма незначительной. Поэтому когда человек говорит что на шарпе писать сильно проще то у меня возникает отчетливое ощущение что на плюсах он просто писать так и не научился.

                        Плюсы, имхо, не любят по двум основным причинам
                        1. Там много legacy-проектов с абсолютно убийственной реализацией тогда как на шарпе проекты в среднем новее. Отсутствие нужды возиться с MFC потому что проект начинали 15 лет назад и теперь без радикальной переделки MFC оттуда не вытравишь любому языку дает много очков вперед :D
                        2. Плюсы учить дольше и кривая обучения там круче, а ошибки в нем более красочны.

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

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


                        1. lair
                          14.09.2015 16:12
                          +2

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

                          … людьми с одинаковой компетенцией и желательно в вакууме.

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

                          Мне до сих пор интересно где-нибудь найти факты о том, сколько нужно времени, чтобы «научиться писать» на C++ и C# «на одном уровне».

                          Но вообще, из «плюсы учить дольше» неизбежно следует «на шарпе писать проще». Потому что иначе почему учить дольше? И весь ваш дальнейший пример это все и подтверждает.

                          Грубо говоря, я могу посадить джуниора писать код на C# для реального проекта. Он (код, не джуниор) будет некрасивым, неэффективным, но он будет работать, и если будет ронять систему, то это будет видно сравнительно легко. Я совершенно не уверен, что все то же самое можно сказать о C++.


                          1. 0xd34df00d
                            14.09.2015 17:35
                            +1

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

                            Не следует.

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


                            1. lair
                              14.09.2015 17:42
                              +1

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

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

                              (ну и вообще, бульдозером ямы не копают)


                              1. 0xd34df00d
                                14.09.2015 19:09
                                +1

                                А почему не все копают — тут-то аналогия и рвётся уже. Впрочем, для аналогий это нормально.

                                Так и скрипт-однодневку будут писать не на C++. Впрочем, и вряд ли на C#.


                          1. 0serg
                            14.09.2015 23:59

                            Но вообще, из «плюсы учить дольше» неизбежно следует «на шарпе писать проще». Потому что иначе почему учить дольше? И весь ваш дальнейший пример это все и подтверждает.


                            Я пытался показать что более длинное обучение в конце может давать и большую награду (пример с иероглифами). Отдельные буквы учить сложнее чем отдельные иероглифы, но выучив их все скачком оказываешься на плато колоссальных возможностей где можно реализовывать сколь угодно сложные тексты не заучивая новых иероглифов. В терминах «кривой обучения», у алфавита она вначале крутая, а затем практически плоская, тогда как у иероглифов она вроде как пологая, но подъем на ней длится неограниченно долго, а у живых людей еще и тупо упирается в конечную емкость памяти. Выше так же приводили прекрасный пример с бульдозером.

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

                            Джуниоры у нас рутинно пишут код и для C++ проекта. Естественно это требует определенного присмотра. Но если объяснить джуниорам несколько простых техник и давать вовремя по рукам при попытке писать свои велосипеды, то у них код будет работать и не будет ронять систему, точно так же как и в шарпе. Я верю что в шарпе без подобного присмотра за джуниорами программа будет падать куда реже чем в плюсах, но, простите, не верю что написанный таким образом код будет легче дебажить или мэйнтэйнить. Будут спагетти с кучей дубликатов и странной логикой и то что оно будет не крэшиться а «просто» выдавать неверные ответы в неожиданных местах, переставать работать при малейших правках и требовать переписывания 90% кода для добавления небольшой фичи окажется слабым утешением.


                            1. lair
                              15.09.2015 00:03

                              Я пытался показать что более длинное обучение в конце может давать и большую награду (пример с иероглифами).

                              Очень плохой пример. Алфавит учится проще и быстрее, чем иероглифическое письмо.

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

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


                              1. 0serg
                                15.09.2015 00:24

                                Очень плохой пример. Алфавит учится проще и быстрее, чем иероглифическое письмо.


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

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


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


                                1. lair
                                  15.09.2015 10:57

                                  Иероглифическое письмо «учится» в понимании «написать примитивнейшее сообщение» значительно быстрее.

                                  У нас с вами разное понимание «учится», отсюда и различие позиций.


                        1. bigfatbrowncat
                          14.09.2015 21:14

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


                          Пример неудачный.

                          Для того, чтобы выучить C++ и C#, необходимо узнать примерно одинаковое количество примерно равно сложных вещей. В C++ будет небольшой перекос в сторону управления памятью и низкоуровневых понтий, в C# будет страшное слово «рефлексия» и мозгодробительный P/Invoke с нитрыми аннотациями. Везде — свои заморочки.

                          Я говорю это как человек, который примерно в равной степени владеет обоими языками. Правда-правда. Что бы обо мне тут не говорили за мою позицию выше, я вполне неплохо способен писать и на «крестах».

                          И именно потому, что я на них пишу, могу сравнивать.

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

                          Мне приходилось ловить странный NullPointerException в Java Enterprise проекте на 1000 с лишним классов. Это было тяжко. Там, кстати, было IoC, которое я сам терпеть ненавижу, но без которого в таком громадном проекте — никуда. И могу сказать, что это было нелегко.

                          Но поймать мелкую багу в C++ коде подчастую — просто кошмарно трудно.

                          И если вы не экстрасенс, то никакие знания и квалификация всм не поможет. Ошибки C++ не прощает.


                          1. 0serg
                            14.09.2015 23:17
                            +1

                            У нас проект на сотни тысяч строк кода и мне доводилось искать в нем кошмарно сложные ошибки. Да, в плюсах это определенный дзэн, да это может требовать знания ассемблера и прочтения манов по x86. Но нет, это вполне реализуемо и значительно проще чем, к примеру, искать ошибки в плохо написанной многопоточной логике. Дебаггер и логгирование способны творить чудеса, самые мегасложные ошибки при понимании того что и как ты делаешь отлаживаются за один-три дня (один кстати раз нашел баг в компиляторе :D — там, впрочем, все было довольно просто, хотя человек не способный проанализировать дизассемблированный код там бы удавился). Да, у меня ушло 15 лет на то чтобы этому научиться. Но, ёклмн, многопоточные баги (которые вообще не зависят от того, шарп это или плюсы) могут ловиться месяцами (их тупо бывает чудовищно сложно воспроизвести), а еще у нас в проекте есть математические/инженерные проблемы которые решаются ГОДАМИ с довольно незначительным прогрессом несмотря на квалификацию занятых в этом решении людей. Вот это я понимаю — сложность. А самые сложные ошибки характерные чисто для плюсов — это так, рутина на несколько дней, достаточно просто понимать куда надо смотреть и методично проверять что там все «как надо». Примерно как старый телевизор ремонтировать, если Вы еще застали то время когда они из дискретных компонентов набирались :)

                            Но ладно, это хвастовство и лирика :). С практической точки зрения куда важнее то что по моему опыту отлова подобных проблем, реально это проблема для считанных процентов от общего объема кода. Подавляющее большинство плюсового кода при минимальной самодисциплине пишется так что подобных проблем там не возникнет практически никогда у самого распоследнего джуниора. Главное по рукам надавать вовремя, чтобы отбить идиотские практики изобретения велосипедов и заставить людей пользоваться стандартными (и что, блин, характерно — удобными) вещами. У нас же ведь как бывает? Смотрит человек на задание и вместо того чтобы покопаться в библиотеке или хотя бы спросить старших берет и пишет свой самоходный веник на паровой тяге. В суровом C-style или напротив с кучей плюсовых наворотов а-ля Александреску. И естественно в половине случаев недооценивает сложность задачи. Но стоит начать использовать, блин, банальнейший STL и оказывается что, во-первых, задача в подавляющем большинстве случаев прекрасно решается штатными средствами этой или другой уже имеющейся библиотеки, а во-вторых получившееся решение работает с первого раза, ничего не крэшит, и — сюрприз — еще и делает это зачастую быстрее чем самопальный код :). Да, есть 1-5% кода где нужен хардкор и требуется определенный опыт. Да, это нередко ключевые компоненты на которых держится половина программы. Но, я Вас уверяю, неважно плюсы или шарп — если Вы на эти компоненты посадите джуниоров, то неизбежно огребете проблем по полной программе.


                            1. bigfatbrowncat
                              15.09.2015 16:02

                              Для людей вашего уровня язык программирования уже значения не имеет. Речь идет о начинающих и о тех, кто в отрасли 2-3 года.

                              Я сам, увы, ассемблер не знаю. Но как функции вызываются, знаю более менее, даже ffi, например, щупал. Но ковыряться в этом всём, когда в голове usability — сущий ад.


                    1. bigfatbrowncat
                      14.09.2015 19:22

                      Гоните ваших «спецов» взашей. Не за то, что он используют С# (он отличен), а за то, что они его использовать не умеют.

                      UI любой сложности на Windows Forms делается так быстро и легко, что даже сравнивать не с чем. Я в институте на нем запилил программу мат моделирования со сменными счетными модулями, плагинами и чертовой тучей настроек. При этом счетный код был написан на C++/CLR. И всё это прекрасно связывалось между собой.

                      А если вы под Mono пишете, то P/Invoke — довольно простая технология. Сложнее, чем JNI, но я не знаю, кем надо быть, чтобы ее не освоить на базовом уровне за неделю.


                      1. 0serg
                        14.09.2015 22:48

                        Там WPF а не Windows Forms. Типа круче и вообще в духе великих идей Микрософта отдадим UI на аутсорс дизайнерам. Ибо великий WPF отделяет presentation от model, так что наши программисты забабахают model, а дальше WPF ее магическим образом привяжет к UI. Я был сильно против, но именно идея с аутсорсом, насколько я понимаю, в итоге «продала» C# менеджменту. Надо ли упоминать о том что на практике эта идея через полгода благополучно отправилась на свалку?

                        P/invoke нормально работает когда код можно свести к некой функции «возьми A и Б, посчитай В(А, Б) и верни результат». И то будет совершенно непонятно нафига нужный геморрой (мы же вроде как себе жизнь упростить хотим, а не усложнять на ровном месте?). А у нас код тянет от драйвера в реальном масштабе времени данные с железа и эти данные тут же в реальном времени на десятках потоков и в сотни шагов обрабатывает. И наладить взаимодействие между этим самоуправляющимся кодом самостоятельно генерирующим события и UI через p/invoke, внезапно, оказывается не тривиально.

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


                        1. bigfatbrowncat
                          15.09.2015 16:05

                          Ибо великий WPF отделяет presentation от model, так что наши программисты забабахают model, а дальше WPF ее магическим образом привяжет к UI. Я был сильно против, но именно идея с аутсорсом, насколько я понимаю, в итоге «продала» C# менеджменту.


                          Архитектуру MVC придумали не в Microsoft. Ей более 40 лет. И то, что современные UI-фреймворки подталкивают к ее использованию — однозначно хорошо. Я насмотрелся на программы, в которых View и Controller перемешаны друг с другом. И как юзер, и как разработчик.

                          Ваша неправота в этом вопросе, однако, не отмняет того факта, что MVC должно быть не только в WPF, но и в голове разработчиков (как и ООП и много других умных вещей). В противном случае норального решения не получится.


                          1. 0serg
                            15.09.2015 20:59

                            Я вовсе не против MVC. Просто там уже не выходит того «легко и просто» о котором Вы пишете и грамотная реализация требует достаточно высокой квалификации и значительной работы и это обесценивает преимущества шарпа — и выигрыш получается (в относительных цифрах) невелик, и джуниора туда уже не поставить. Кроме того этот пример хорошо показывает что на бумаге микрософтовские технологии типа WPF очень удобны и позволяют делать крутые вещи, а как доходит до реализации — половина обещанного не срастается, а вторая половина неудобна.


                            1. lair
                              15.09.2015 21:10
                              +1

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

                              К счастью, это относится не ко всем технологиям MS.


                            1. bigfatbrowncat
                              15.09.2015 21:16

                              Я ничего про «легко и просто» не писал. MVC — это не просто. Но это — чуть ли не единственный подход, который позволяет поддержиывать крупные проекты со сложным интерфейсом.


                              1. lair
                                15.09.2015 21:29
                                +2

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


                                1. bigfatbrowncat
                                  15.09.2015 22:00

                                  Вы правы. Я говорю об MVC как о самой идее отделения логики от представления. То есть сам факт, что такое отделение в серьезном проекте необходимо, сомнений не вызывает.


      1. 0serg
        07.09.2015 22:55
        +4

        Эти проблемы (если они есть) тривиально профайлером вылавливаются и устраняются в солидных размеров проекте где работают десятки программистов за пару часов работы одного человека


        1. gandjustas
          07.09.2015 23:10
          -2

          На моей практике из 10 программистов профайлером умели пользоваться в среднем 4, меньше половины.


          1. 0serg
            07.09.2015 23:27
            +5

            ИМХО на команду из 20 человек за глаза хватит и одного умеющего пользоваться профайлером :)
            Но проверить не могу, поскольку в моей компании профайлер худо-бедно умели использовать все


            1. 0xd34df00d
              08.09.2015 14:34

              Да. Более того, это заразительно.

              Вот пришёл я в команду, где профайлерами особо не пользовались. Был у меня предыдущий опыт с Intel VTune, использовал его для своих pet project'ов. На работе его не было, попросил купить лицензии — купили, начал им успешно пользоваться по мере необходимости.

              Пара коллег уже обратила внимание, мол, ой, а что это у тебя за такие прикольные таблички, деревья и цветные графики? А покажи! А научи! А давайте ещё лицензий купим! Теперь в команде больше одного человека, пользующегося профайлером :)

              (тут ещё, кстати, не могу не вспомнить замечательных авторов PVS-Studio с их замечательной политикой выдачи беток и всего прочего только при разговоре как с представителем компании)


  1. maaGames
    07.09.2015 17:20
    +13

    > Поэтому vector использует динамическую память для хранения массива и должен честно проверять выход за границы.
    В релизе vector[] НЕ проверяет выход за границы. Если хочется «честногО» сравнения, используйте vector.at()

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

    Типовой код. Бабл сорт. Типовой. Большая вероятность… Какой смысл сравнивать производительность типовых лабораторных работ первокурсников?


    1. gandjustas
      07.09.2015 17:28
      -6

      Замените бабл сорт на свертку. По большому счету ничего не изменится.

      В релизе vector[] НЕ проверяет выход за границы.

      Однако…


      1. maaGames
        07.09.2015 17:31
        +10

        > Те кто знают (или думают что знают) C++
        Классно вы себя приложили.) Различие между [] и at именно в том, что проверка выхода за границы в релизе есть только у метода at. Встречал кривые реализации, где скобки даже в дебаге границы не проверяли. Именно поэтому между массивом и vector в релизе разница околонулевая (на усмотрение компилятора).


        1. gandjustas
          07.09.2015 17:33
          -6

          Я не сравнивал детали (мне они не интересны), я сравнивал код, который может написать человек. При прочих равных 9 из 10 напишут [], а не at. То что [] позволяет отстрелить себе ноги — это прекрасно.


          1. maaGames
            07.09.2015 17:41
            +32

            Вот и я о том же! Сперва один сравнивает языки неадекватным способом. Затем другой, пытается доказать неправоту первого. При этом оба не знают тонкостей «противного» им языка.
            Допустим, что сравниваем производительность пузырька, мне не жалко. Но! Программу на С++ должен писать хорошо разбирающийся в С++ программист, а на C# — разбирающийся в C#. Без обид, но С++ вы если и знаете, то не сильно плотно. А я не смогу написать максимально эффективно на C#, только если случайно совпадёт. Т.е. все эти три статьи о «сравнении» языков — пердёж в лужу (извините, не ругайте).

            C-style нужно делать через указатели. Почти 100% гарантия того, что будет самый эффективный вариант. Если компилятор индексированный доступ сам не смог в указатели переделать.


            1. gandjustas
              07.09.2015 23:13
              -9

              Сделайте форк, улучшите код. Вам кто мешает?
              Вы же хорошо разбираетесь в C++?


  1. maydjin
    07.09.2015 17:29
    +13

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


    1. gandjustas
      07.09.2015 17:34
      -5

      Например?


      1. maydjin
        07.09.2015 17:41
        +16

        Любая графика, ибо смотрит на неё человек а в секунде не так уж и много милисекунд.

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


        1. vanxant
          07.09.2015 19:07
          +4

          Перефразируя, трупут это тупо деньги.
          А вот лэтенси это искусство.


        1. gandjustas
          07.09.2015 23:17
          -4

          Правильно все, но C++ и вообще скорость кода не при чем в большинстве случаев.
          Графика давно делается на видеокартах и руками никто пишет текстурирование. Физика в играх — векторные вычисления, для них есть SIMD в .NET 4.6 (в этом сравнении нет).
          Сетевые фс и прочие серверы упираются в IO, поэтому им скорость кода до одного места.
          Трейдинговые системы, кроме HFT, не требуют реакции в 10мс. Ордер от обычного терминала исполняется минутами,10мс ничего не решат.


          1. maydjin
            08.09.2015 00:26
            +3

            По большому счёту — согласен.

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

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

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

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

            Из областей где ещё может понадобиться быстрый код это например парсера — что бы упереться в i/o надо всё таки сначала успеть всё разгрести и подготовить в нужном формате, а так же дать время выполниться полезной нагрузке. И криптография, хотя там обычно всё таки C а не кресты, да и многие вещи наверное тоже можно порешать аппаратно.


            1. gandjustas
              08.09.2015 00:37
              -5

              Однако, многие готовы перестраховаться и переплатить (сейчас их всё меньше). Ибо, если ты не можешь масштабироваться вширь, то экономить на вертикальном масштабировании как минимум глупо, зато делать это железом чаще дешевле.
              Это вы о чем? Все масштабируемые системы вовсе не на C++ написаны, да и как связаны 10мс и масштабируемость?

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

              Ну и больше субьективное мнение — при должном размере и скорости кода, а так же при грамотном ручном управлении памятью, таки общий прогресс системы всё таки будет выше за заданный квант времени (просто не всегда бывает нужен выше).
              А кто спорит? Только это вы не про C++ пишите. Он, к сожалению, делает довольно много работы (подсчет ссылок, вызов деструкторов, выделение\освобождение памяти). Это на голом C или C_с_классами можно все контролировать, но и вероятность ошибиться на голом C в разы выше.


              1. maydjin
                08.09.2015 01:07
                +4

                О_О. Подсчёт ссылок в c++? Походу, я чего то не знаю…

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

                >да и как связаны 10мс и масштабируемость

                Вот стоит у вас задача, за 100 мс обработать 10 запросов. А потом появилась задача обработать 1000 запросов. За 10 мс каждый. Потом ещё, потом ваша железяка за 3ккк не потянула. На ipc при горизонтальном масштабировании — тратиться 10мс. Вы уже не можете утверждать что можете масштабироваться горизонтально бескровно. Если речь идёт о любом маломальском реалтайме (что то нету в CS 500 на 500 баталий, хотя казалось бы мультикаст всех спасёт), то вы в принципе не можете масштабироваться горизонтально ибо на ipc у вас уходит больше времени, чем нужно на обработку запроса (надо же ещё пэйлоад уместить).

                Выход — масштабироваться вертикально. Покупать 10G сетевухи, крутую мать, кидать на неё процов, памяти и производить ipc за более короткое время, так как оно перестаёт быть собственно ipc, а становиться чтением записью памяти. А так же утилизировать это всё максимально экономно.

                P.S. CS — чисто первое что в голову пришло, но факт что в тех же сетевых игрушках не просто так мир разбит на зоны, а комнаты имеют вместимость.


                1. gandjustas
                  08.09.2015 10:14
                  -7

                  О_О. Подсчёт ссылок в c++? Походу, я чего то не знаю…

                  Смартпоинтерами не пользуетесь?

                  Нет, ну есть конечно всякие умные указатели, однако без них кресты не прям таки сразу превращаются в C_с_чем бы то ни было.
                  Именно сразу и превращаются. По большому счету в чем разница между new\delete и malloc\free, если каждый руками выписывать?

                  Вот стоит у вас задача, за 100 мс обработать 10 запросов.

                  Когда запрос приходит по сети, то большая часть времени тратится на сетевой IO. Очевидно что в этом случае надо не ждать пока весь запрос будет получен, а начинать обрабатывать пока клиент шлет байты. Например в RavenDB (NoSQL база на .NET) чуваки сделали так, что умудряются писать на диск пока клиент отправляет данные.

                  Когда сможете повторить такое на плюсах — приходите поговорить о массовой обработке запросов.


                  1. encyclopedist
                    08.09.2015 10:41
                    +4

                    Смартпоинтерами не пользуетесь?

                    unique_ptr не содержит никакого подсчёта ссылок и не даёт накладных расходов. shared_ptr это специальная вещь, которой пользуются только когда он действительно нужен.

                    Именно сразу и превращаются. По большому счету в чем разница между new\delete и malloc\free, если каждый руками выписывать?
                    — Ни во что не превращается. Отсутствие new/delete никак не связано с умными указателями. Я вот пишу код без new и без умных указателей. Да и по большей части без указателей вообще.

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


                    1. gandjustas
                      08.09.2015 13:17
                      -4

                      unique_ptr не содержит никакого подсчёта ссылок и не даёт накладных расходов. shared_ptr это специальная вещь, которой пользуются только когда он действительно нужен.

                      unique_ptr нельзя передать просто в метод. А если метод может сделать что угодно, то ничего кроме shared_ptr вообще передавать нельзя.

                      Я вот пишу код без new и без умных указателей. Да и по большей части без указателей вообще.

                      Искренне рад, что у вас такие простые задачи.


                      1. Pushkoff
                        08.09.2015 13:34
                        +2

                        > unique_ptr нельзя передать просто в метод.
                        можно передать по ссылке


                      1. encyclopedist
                        08.09.2015 13:38
                        +4

                        unique_ptr нельзя передать просто в метод. А если метод может сделать что угодно, то ничего кроме shared_ptr вообще передавать нельзя.

                        — остановитесь пожалуйста писать бред.

                        unique_ptr можно передавать в метод. Это будет означать передачу владения. Если же владение передавать не надо, то передаётся обычный указатель с помощью p.get(). Также можно передать ссылку на объект.

                        Если же ваш метод делает вообще все что угодно, то я даже не знаю как это комментировать. Тут вам ничего не поможет. Даже C#.

                        Искренне рад, что у вас такие простые задачи.

                        Объекты хранятся в контейнерах, доступ осуществляется по итераторам. Стандартная библиотека все делает за меня. И от сложности задачи это слабо зависит. Конечно есть случаи, когда нужны new, указатели и умные указатели, но это совсем не основной стиль использования современного C++. new при этом обычно размещается в конструкторе некоего класса, delete в десрукторе, и дальше работает RAII.


                  1. encyclopedist
                    08.09.2015 10:44
                    +2

                    Когда запрос приходит по сети, то большая часть времени тратится на сетевой IO. Очевидно что в этом случае надо не ждать пока весь запрос будет получен, а начинать обрабатывать пока клиент шлет байты. Например в RavenDB (NoSQL база на .NET) чуваки сделали так, что умудряются писать на диск пока клиент отправляет данные.

                    Когда сможете повторить такое на плюсах — приходите поговорить о массовой обработке запросов.
                    — У тех кто этим занимается никаких проблем нет. Вы например про boost.ASIO что-нибудь слышали?


                    1. gandjustas
                      08.09.2015 11:50
                      -5

                      Не только слышал, но и видел, поэтому и говорю — приходите как сможете повторить.


                  1. Chaos_Optima
                    08.09.2015 11:34
                    +3

                    Именно сразу и превращаются. По большому счету в чем разница между new\delete и malloc\free, если каждый руками выписывать?

                    То есть для вас С++ это исключительно использование умных указателей? Шаблоны, RAII, ООП, оказывается это всё ерунда, о чём я думал ((. Я например когда писал свой парсер умные указатели не использовал, я вообще писал свой аллокатор, который освобождал потом всю память махом когда он переставала быть нужной. Чем дальше вы пишите тем яснее становится что навыки использования С++ у вас совсем скудные.


                    1. gandjustas
                      08.09.2015 11:54
                      -7

                      Интересно, как вы собрались RAII делать без умных указателей?
                      ООП — это реально ерунда, stl вообще без ООП сделан и выглядит гораздо лучше, чем если бы его сделали на ООП.
                      Шаблоны — хорошая штука для библиотечного кода, но для прикладных задач вполне можно без них обойтись.


                      1. Chaos_Optima
                        08.09.2015 12:09
                        +3

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

                        class Abc
                        {
                          string A;
                          map<string, vector<string>> B
                          tuple<string, vector<string>> C
                        }
                        

                        У всех его членов вызовется деструктор без какого либо явного вмешательства пользователя.
                        ООП — это реально ерунда, stl вообще без ООП сделан и выглядит гораздо лучше, чем если бы его сделали на ООП.

                        Это как бы неправда любой контейнер в stl имеет определённую иерархию (как минимум в реализации от MS)
                        Шаблоны — хорошая штука для библиотечного кода, но для прикладных задач вполне можно без них обойтись.

                        Да но тогда придётся отказаться от stl или использование шаблонов и их написание это взаимоисключающие вещи? И опять же, да для проектов Hello world они и правда ненужны, но вот в реальности всё не так радужно.


                        1. gandjustas
                          08.09.2015 12:38
                          -4

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

                          То что вы можете в подмножестве кода обойтись без умных указателей не означает, что можно писать идиоматичный C++ код вообще без них.

                          Это как бы неправда любой контейнер в stl имеет определённую иерархию (как минимум в реализации от MS)
                          Это детали реализации, сравни с контейнерной библиотекой C#\Java, там из всех ушей ООП торчит/

                          Да но тогда придётся отказаться от stl или использование шаблонов и их написание это взаимоисключающие вещи? И опять же, да для проектов Hello world они и правда ненужны, но вот в реальности всё не так радужно.
                          В реальности прикладной код (который решает бизнес-задачу) почти не требует шаблонов. Прикладной код конкретный, а не обобщенный.

                          Вот в Go выкрутились, там нет шаблонов и генериков, тем не менее массивы и коллекции представляют из себя обобщенные типы и есть обобщенные функции. Свои такие функции создать нельзя. Это напрягает, но тем не менее писать прикладной код не мешает.

                          Не спорю при этом, что для библиотечного кода прекрасно подходят шаблоны и именно из за шаблонов stl крут.


                          1. Chaos_Optima
                            08.09.2015 12:53
                            +1

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

                            То что вы можете в подмножестве кода обойтись без умных указателей не означает, что можно писать идиоматичный C++ код вообще без них.

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

                            Да )) и эта деталь означает что stl использует ООП
                            В реальности прикладной код (который решает бизнес-задачу) почти не требует шаблонов. Прикладной код конкретный, а не обобщенный.

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


                            1. gandjustas
                              08.09.2015 12:56
                              -5

                              У меня например ещё не было ни одного проекта где бы я не писал шаблоны.

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


                              1. 0xd34df00d
                                08.09.2015 15:23
                                +2

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

                                А прожить можно и без C вообще, на голом ассемблере писать.

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


                  1. maydjin
                    08.09.2015 12:30

                    Разница — в RAII, которое не строго равно умным указателям. Умные указатели это ширпотреб для случаев когда важнее внятно записать бизнес. Однако, есть ещё размещение например, где RAII также остаётся в силе.
                    Не просто так эту концепцию таки стали потихоньку пилить и в .net и в java, посредством всяких with и lock.

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

                    > Когда запрос приходит по сети, то большая часть времени тратится на сетевой IO.

                    Зависит исключительно от типа полезной нагрузки. Выполнять i/o одновременно с обработкой данных это квинтэссенция современного серверного ПО. Так делают хоть на эрланге хоть на плюсах, никакого рокетсайнс там нет.


                    1. gandjustas
                      08.09.2015 12:46
                      -1

                      Это в эрланге нет, а в плюсах — еще какой. Даже нагуглить такой код на плюсах проблематично.

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

                      Например в случае визуального редактора с undo-redo и нетривиальными объектами это уже крайне сложно сделать. Я сам такое писал примерно в 2006 году, и не зная буста и начитавшись александреску я изобретал свои smart_ptr для этой задачи.


                      1. maydjin
                        08.09.2015 13:27

                        Сложные задачи — надо декомпозировать. А над архитектурой — задумываться. Подсчёт ссылок был сделан для того, что бы сократить трудозатраты на эти задачи, особенно в контексте потоков. Для этого же он служит и в плюсах, однако, тут никто не заставляет использовать его онли.


                      1. 0xd34df00d
                        08.09.2015 15:26
                        +1

                        В случае визуального редактора и undo-redo время нажатия Ctrl+Z пользователем будет на многие порядки больше оверхеда от shared_ptr.

                        А я вот парсеры натуральных языков пишу, и как-то умудряюсь во времена масштаба десятков-сотен микросекунд (микро, Карл!) вместить разбор поступающего запроса, спеллчек (умный, с language model'ами на десятки гигабайт), прогон собственно парсинга и ранжирование.

                        На плюсах, да.


                        1. maaGames
                          08.09.2015 15:35

                          Так вы же читерите там! Ищете словоформы по хэшам бинарным поиском, а надо строго линейным! Дважды, чтобы наверняка! Иначе не честно.


                      1. maaGames
                        08.09.2015 15:29

                        Если вы теряете ВСЮ производительность из-за подсчёта ссылок, то вы явно делаете что-то не так. Самый простой вариант — сделать интрузивный подсчёт ссылок, тогда он получается практически бесплатный, потому что счётчик находится в объекте, а не хранится где-то отдельно и нет лишней беготни по памяти — минимум кэш миссов.
                        Ничего личного, но в 2006 году знаний С++ у вас было меньше, чем сейчас, поэтому что вы там натворили — одному Богу известно. А говнокод может тормозить по любому поводу.


          1. Chaos_Optima
            08.09.2015 11:27
            +2

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


            1. gandjustas
              08.09.2015 12:02
              -3

              Тем не менее огромное количество игр делается на Unity, который, внимание, C#. Так что непонятно что вы пытаетесь сказать. Исходный посыл был в том, что ради 10мс стоит заниматься C++, я лишь сказал что в играх не часто встречается эта проблема.

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


              1. Chaos_Optima
                08.09.2015 12:14
                +6

                Тем не менее огромное количество игр делается на Unity, который, внимание, C#

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

                Именно что для игровой логики которая является наименьшей проблемой для производительности, ваш кэп. Ну и да, чаще всего стараются выбрать наиболее быстрые скриптовые языки, lua, AS, JS/


                1. gandjustas
                  08.09.2015 12:51
                  -3

                  Который, внимание, С++. С# используется лишь для скриптования игровой логики, упс.

                  Как же люди целые игры пишут только на C#, они наверное не знают что там надо C++ использовать.

                  Именно что для игровой логики которая является наименьшей проблемой для производительности, ваш кэп
                  Она является наибольшей. Помню игру СТАЛКЕР, у которой логика на Lua. Бегаешь по полям — 30+ fps, появляются 3-4 противника (не в кадре, а просто в окружении) — 12 fps. Это ты называешь наименьшей проблемой? Или цивилизация, в которой противники ходят минутами это меньшая проблема?


                  1. Chaos_Optima
                    08.09.2015 13:00
                    +2

                    Как же люди целые игры пишут только на C#, они наверное не знают что там надо C++ использовать.

                    Я говорил про сам движок, который написан на С++, а не про пользователей этого движка. Повторюсь игровая логика зачастую является наименьшей проблемой для производительности.
                    Она является наибольшей. Помню игру СТАЛКЕР, у которой логика на Lua. Бегаешь по полям — 30+ fps, появляются 3-4 противника (не в кадре, а просто в окружении) — 12 fps. Это ты называешь наименьшей проблемой?
                    Да это наименьшая проблема, я не знаю как устроен движок для сталкера, но склонен думать что это проблема не скриптового языка а организации архитектуры в целом.


                    1. gandjustas
                      08.09.2015 13:26
                      -2

                      Я говорил про сам движок, который написан на С++, а не про пользователей этого движка.

                      Да хоть на ассемблере, без разницы.
                      А пользователи движка не программируют графику и физику на C#? Или они там магически сами считаются?

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

                      В тупых коридорных шутерах поведение врагов примитивное и там скрипты действительно не проблема. А в игрушках типа цивилизации, где вся логика на python, скорость скриптов — основная проблема. Тем не менее на C++ не переписывают что-то.


                      1. Ogra
                        08.09.2015 13:34
                        +3

                        А пользователи движка не программируют графику и физику на C#? Или они там магически сами считаются?


                        Графику и физику — нет. Пользователи лишь отдают движку граф сцены, а тот, написанный на С++, отрисовывает все как надо. Физический движок тоже на С++ написан. То, что в C# проброшены интерфейсы к физике, ничего не меняет.


                        1. gandjustas
                          08.09.2015 14:39
                          -4

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


                          1. Ogra
                            08.09.2015 14:58

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


                      1. Chaos_Optima
                        08.09.2015 14:10

                        А пользователи движка не программируют графику и физику на C#?

                        Нет.
                        они там магически сами считаются?

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


                        1. gandjustas
                          08.09.2015 14:38
                          -1

                          С саппортом общался. Я как раз думал что тормозит из-за графики. Понижал настройки — все равно тормозит. Потом спросил что за фигня, говорят процессор слабый и не справляется с AI. Потом выяснил что весь этот AI сделан скриптами в Lua.


                          1. Chaos_Optima
                            08.09.2015 15:09

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


              1. Chaos_Optima
                08.09.2015 12:24

                Кстати ещё дополню.

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

                Расскажите это пожалуйста людям которые используют Unreal engine для разработок AAA игр. По видимому они зря используют С++ в качестве основного языка для кодирования игровой логики.


                1. gandjustas
                  08.09.2015 12:54

                  Может и не зря, я не знаю всех обстоятельств. Но есть куча игр со скриптами (Lua, Python) ты считаешь что они зря это делают и надо все на C++ переписать?


          1. ZakharS
            09.09.2015 10:04

            Хм… А мы тут пытаемся на несколько десятков микросекунд выиграть… Да, это HFT.


      1. Wedmer
        07.09.2015 17:52
        +6

        Система распознавания человека на путях в метро. За 100ms на дохлом cortex-a8 надо кучу аналитики провести. А ведь еще приходит куча данных от других датчиков.


        1. Goodkat
          07.09.2015 18:03
          -5

          Для ваших задач, небось, и С++ покажется слишком медленным, и будете писать на чистом С :)


          1. Wedmer
            07.09.2015 18:24

            На данный момент все устраивает. Даже есть большой запас по производительности. Код, который отъедал 100% процессорного времени, теперь редко достигает 0,1% на тех же задачах)


  1. wAngel
    07.09.2015 17:35

    Скажите, почему в примерах для C# нет «прогрева» JIT?


    1. gandjustas
      07.09.2015 17:39

      Есть, смотрите исходник на github.


  1. encyclopedist
    07.09.2015 17:49
    +6

    Кстати, если уж вы за идиоматичность, то в коде на C++ стоит использовать std::swap(m[i], m[j])


    1. Door
      07.09.2015 17:55
      +6

      к сожалению, речь о идиоматичности не идёт — пузырьковую сортировку, написанную ручками, кто использует?


      1. gandjustas
        07.09.2015 23:20
        -2

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


    1. gandjustas
      07.09.2015 23:18
      -2

      Хотел и так написать, но аналога для C#, даже близкого, нету.


    1. gandjustas
      08.09.2015 14:31
      -2

      Сделал swap и однозначно скажу — не надо его использовать. В дебаге тормозит так, что работать невозможно.


      1. withkittens
        08.09.2015 15:47
        +1

        Тогда и итераторы в stl на помойку! В дебаге тормозят так, что аж мама не горюй ;)


    1. 0xd34df00d
      08.09.2015 15:29
      +1

      Идиоматично в C++ делать

      using std::swap;
      swap(m[i], m[j]);
      


  1. stavinsky
    07.09.2015 18:06

    Кстати вопрос: а корректно ли использовать измерение времени выполнения тем же языком который мы поставили под микроскоп? Может все же внешнюю утилиту для этого использовать? И одну на оба теста


    1. Mogost
      08.09.2015 07:59

      Тогда это не позволит оценить такие моменты, как прогрев C# кода.


  1. abby
    07.09.2015 18:16
    +3

    Во-первых, напомнило python, где тут же налетят и предложат десять способов написать правильный for, да еще и для разных версий.

    По статье:

    • Все таки типовой код скорее всего работает с полями объектов или, по крайней мере, структур, аллоцирует большое количество новых объектов, частенько обращается к уже выгруженным страницам памяти и так далее. Так что навряд ли вы встретите сортировку чисел пузырьком в большинстве программ.
    • Это хорошо, что Вы тестируете на одних и тех же данных, но в чем смысл сортировать уже отсортированный массив?
    • Да и вообще, производительность числодробильного кода и там и там должна быть примерно одинаковая, основной источних тормозов — неучтенная работа с чем-то медленным, потом работа с памятью, и с большим отставанием идет кривая архитектура.
    • В программах C++ все же довольно часто прибегают к тем или иным способам оптимизации. И там и там сначала профилирование, анализ данных, а потом оптимизация.


    1. maaGames
      07.09.2015 18:28
      +1

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


  1. u_story
    07.09.2015 18:19

    А какой JIT использовался? В 4.6 по дефолту ryujit уже стоит?
    Можете попробовать прогнать тесты с другим старым\новым JIT?


    1. gandjustas
      07.09.2015 23:23

      Насколько я понял в .NET 4.6 x64 по дефолту ryujit. blogs.msdn.com/b/clrcodegeneration/archive/2015/05/27/ryujit-and-net-4-6.aspx
      Скорее всего под него есть свои хитрости оптимизации, но я не вникал.


  1. JIghtuse
    07.09.2015 18:20
    +4

    В большом приложении такой оверхед сожрет весь выигрыш от использования C++.

    Маловероятно. В каждом проекте узким горлышком будет своё место, и без профилирования делать такие выводы не стоит. Забыли поставить амперсанд — профайлер вам подскажет. Соглашусь всё же, что это ближе к коду на C#. Но на мой взгляд обе статьи занимаются странным. В любом случае сравнивается две конкретные реализации языков, имеющие нечто общее, но в целом принципиально по-разному устроенные. Что, если взять другую платформу? Другой компилятор и набор опций? Заглянуть наконец-то в профайлер?


    1. gandjustas
      07.09.2015 23:29

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

      Обычно узкое место не в коде, а в алгоритме или периферийных устройствах. Поэтому горлышки будут как на C#, так и на C++.


      1. 0xd34df00d
        08.09.2015 15:33
        +1

        Вот нужно мне было загружать файл с таблицей вида слово1\tслово2\tчисло. Изначально там был std::istringstream. Тормозит, скажем, 95 секунд грузится на 170 миллионах строк.

        Выкинул istringstream, взял вызов mmap(), взял вместо строк boost::string_ref, написал свой парсер слов и чисел (благо, формат весьма жёсткий) — опа, 50 секунд. Дальше ускориться я уже не осилил :(


  1. evocatus
    07.09.2015 18:49
    +4

    Скажите, а Вы убедились, что во всех примерах процессор работает на одинаковой частоте?


    1. gandjustas
      07.09.2015 23:30
      +1

      Я запускал две программы одновременно порядка 20 раз.


  1. Bas1l
    07.09.2015 19:25
    +1

    В обеих статьях, мне кажется, упускают как минимум garbage collection. Даже если весь ассемблерный код, кроме деаллокации, будет идентичным, C# будет медленнее (тестов у меня, конечно, нет, и все зависит от «паттернов» аллокации-деаллокации, но тем не менее). Кроме того, задержки будут происходить в непредсказуемое время.


    1. lair
      07.09.2015 20:19
      +2

      Даже если весь ассемблерный код, кроме деаллокации, будет идентичным, C# будет медленнее (тестов у меня, конечно, нет, и все зависит от «паттернов» аллокации-деаллокации, но тем не менее).

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


      1. JediPhilosopher
        08.09.2015 13:18
        +1

        На ответ конкретно этому клиенту может и не повлияет. А вот следующему, на ответ которому уже не хватит памяти и придется делать GC и отдуваться сразу за всех — очень даже может быть.
        И я реально с таким сталкивался, приходилось оптимизировать аллокации и ковырять настройки GC.


        1. lair
          08.09.2015 13:24
          +1

          Ситуаций «не хватило памяти — решили сделать GC», конечно, лучше избегать.

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


    1. lockywolf
      07.09.2015 20:55

      Для плюсов тоже есть сборщики мусора, если хочется.


      1. Bas1l
        08.09.2015 13:57

        Лично мне не хочется, как раз наоборот.


        1. FiresShadow
          08.09.2015 14:16

          Есть способ и в С++ мусор автоматически собирать, но при его использования грань между С++ и С# становится весьма условной.


    1. VenomBlood
      07.09.2015 22:13
      +1

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


      1. bigfatbrowncat
        15.09.2015 21:31

        Хоть я и не сторонник C++ в сложных программах, но вынужден признать, что работа с памятью — слабое место мусоросборных языков. И в первую очередь, сложность в том, что GC почти неуправляем и труднопредсказуем.


        1. VenomBlood
          15.09.2015 21:34

          Еще раз перечитайте. В C# выделение объекта на куче проще и быстрее, что делает его в определенных задачах быстрее. Но конкретно судить о языке по паре синтетических тестов все равно несостоятельно.


          1. GrigoryPerepechko
            27.09.2015 13:40
            +1

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


    1. gandjustas
      07.09.2015 23:44

      Если обратишь внимание, то код тестов выполняется 100 раз, выделяя в каждом 40000 байт (+оверхед), это выше границы поколения, поэтому затраты на сборку мусора включены в измерения.
      За счет того, что GC убирает мусор большими объемами, он гораздо эффективнее чем одиночные деаллокации в C++.
      Например, если прогнать просто цикл с new\delete в C++, то он окажется гораздо медленнее цикла с new в C#.


      1. Bas1l
        08.09.2015 13:55

        Честно говоря, в первый раз слышу такую идею. Даже в Рихтере (CLR via C# который) про такое не пишут, кажется. Я не совсем понимаю, почему GC будет быстрее, чем С++ деаллокация, если собирает большими объемами. Вот почему будет медленее легко можно сказать: нужно остановить рабочий поток, запустить GC, протрекать, на какие объекты есть ссылки из стека (пройти весь стек, дерево объектов), записать адреса объектов в очередь freachable, и т.п. Я согласен, что если делать GC редко и удалять много, то вроде бы будет быстрее, чем если делать GC часто и удалять мало. Но это все равно будет медленнее, чем детерминистическая деаллокация С++, при которой просто вызоваются деструкторы в нужных местах (которые все равно будут вызываться при GC). Короче, деструкторы всегда в сумме займут одно и то же время, а вот оверхед есть только в GC.


        1. Ogra
          08.09.2015 14:03
          +2

          Меньше фрагментация кучи, кстати.

          Например, у нас есть три объекта в памяти, А, Б, В.
          ++++++АААА, ББ, ВВВВВВ+++++++ (+ — память занятая другими объектами)

          Удаляем объект А:
          ++++++----, ББ, ВВВВВВ+++++++ Надо добавить освободившуюся память в список свободных блоков. +1 блок

          Удаляем объект В:
          ++++++----, ББ,------+++++++ Надо добавить освободившуюся память в список свободных блоков. + 2 блока

          Удаляем объект Б:
          ++++++----,--,------++++++++ 3 блока
          ++++++------------+++++++ или дефрагментация

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


  1. RPG
    07.09.2015 21:21
    +3

    В режиме x86 оптимизатор полностью выкинул сортировку для std::array, поэтому получилось 0. В реальности работает чуть быстрее, чем C-style массив за счет отсутствия аллокаций.

    asm volatile("");
    

    А вообще следует закругляться со сравнением языков X vs Y на тривиальных задачах, особенно сравнивая C++ с Язык Y (всегда найдётся человек, который перепишет ваш код на SSE4.2+OMP, и сравнение завершится не в пользу последнего). Не верите — посмотрите на очень забавный сайт, где участники буквально соревнуются в искусном владении машинным кодом. Сейчас всех волнует не столько скорость, сколько потребление ресурсов и отзывчивость, если уж C++-разработчики добиваются весьма впечатлительных результатов, было бы любопытно посмотреть на языки с автоматическим управлением памятью в аналогичных условиях…


    1. gandjustas
      07.09.2015 23:56

      Мне неинтересно кто и как извращается. Я в свое время тоже извращался, упаковывая программы с окнами и IO в сотни байт на assembler, но вырос из этого возраста.

      Еще раз повторю: мне интересно было сравнить быстродействие двух кусков кода, которые очень похожи на те, которые напишут 9 из 10 программистов.


  1. Reeze
    07.09.2015 22:08
    +5

    Было бы интересно увидеть сравнение при .NET Native


    1. gandjustas
      07.09.2015 23:45
      -4

      Сделайте форк, добавьте тест в universal app и .NET Native.


    1. gandjustas
      08.09.2015 14:30

      Сделал тест для Native


  1. ilyanik
    07.09.2015 22:29
    -1

    Я тут по работе написал logging library на C++, со всевозможными блекджеками и шлюхами. По ходу дела обнаружил spdlog, и оптимизировал, пока не добился аналогичной производительности (около 3 миллионов форматированных сообщений в секунду). А потом сделал wrapper для C# (который делает только меньшую часть форматирования, и вызывает C++ код). Производительность C# меньше в 6 раз.


    1. withkittens
      07.09.2015 23:11
      +3

      Это вы от Marshalling хотите быстродействия?


  1. 0serg
    07.09.2015 23:22
    +4

    Если в C++ коде мне встречается настолько простой кусок кода, который при этом жрет приличное количество ресурсов, то я его в плюсах могу скомпилировать ICC или ручками вписать интринсики для SSE/AVX, благо что на плюсах это несложно. Обычно код удается подобным образом ускорить вдвое (но с большим разбросом, где-то и вчетверо, где-то на 20%). В шарпе подобное, насколько я понимаю, невозможно. На тривиальном коде до оптимизации, наверное шарп действительно благодаря JIT-у после «прогрева» будет медленнее «всего» на 20%, на оптимизированном вручную — сомневаюсь.

    Но у меня в проектах подобные тривиальные куски кода где не требуется работа с памятью — редкость. Практически весь реальный код требует аллокации и освобождения памяти и там, сдается мне, шарпу резко станет хуже. Из интересного, к примеру, несколько дней возился с кодом который реализовывал многомерную аппроксимацию некоторой функции разложением в ряд Тейлора второй степени. Представьте себе квадратичный многочлен от N переменных, для которого сложение определено тривиальным образом, а умножение отбрасывает степени полинома выше второй. Математика там была тривиальной, а вот работа с памятью требовала эффективно аллоцировать и деаллоцировать кучу мелких объектов и объединять их затем в объекты покрупнее. Ну и взять N=600, несколько десятков тысяч операций с полиномами, и все это должно работать в рантайме, ибо является частью 3D-сканера который на лету должен обработать входящий поток данных. Ухайдокал рабочую неделю, но ускорил код вчетверо — не прибегая, заметьте, ни к какому «C-style» программированию с голыми указателями. С трудом представляю как на этой же задаче работал бы шарп.

    И, все же в исходной задаче вызывает определенные сомнения методика работы с памятью. Я не спец по шарпу, поэтому мне сложно судить насколько адекватен вызов GC.collect в конце программы. Но на первый взгляд для сравнения это совершенно адекватный ход, поскольку финальное состояние программы в противном случае будет разным, ибо C++ код в конце выполнения никому ничего не должен, а шарповый имеет кучу несобранного мусора, на освобождение которого потом — уже вне измеряемого цикла — будет потрачено сколько-то времени. Не получается ли так, что Вы банально вынесли работу с GC за пределы измерения и, условно говоря, если Ваш цикл прокрутить не 100 раз, а 100.000 раз, то поначалу все будет хорошо, а на какой-нибудь 5.643-й итерации отжираемая небольшими кусочками память таки закончится и шарпу резко и внезапно поплохеет? В силу плохого понимания того почему GC.collect вдруг «портит оптимизацию» я допускаю что ошибаюсь и Ваш подход верен, но было бы как бы неплохо Ваш подход как-то обосновать.


    1. gandjustas
      07.09.2015 23:50
      -1

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


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

      Математика там была тривиальной, а вот работа с памятью требовала эффективно аллоцировать и деаллоцировать кучу мелких объектов и объединять их затем в объекты покрупнее.
      Если объекты короткоживущие, то C# сильно быстрее C++ будет. У C++ встроенный аллокатор медленный, в каждой второй advanced c++ книге выдумывают свой аллокатор по этому поводу.
      Если мелкие объекты должгоживущие, то нужно в C# извращаться, создавая свои пулы из массивов структур.


      1. 0serg
        08.09.2015 09:33
        +1

        Я не вижу проблем заменить аллокаторы, это несложно и в наших проектах там где это актуально используется.
        Но здесь размер объекта не фиксирован и может сильно варьироваться, поэтому простой подход не прокатывает
        И не надо катить бочку на плюсовый аллокатор. Штатный аллокатор (а точнее malloc) — это маленький шедевр программирования и он _очень_ эффективен для своей универсальности. Понимаете, проблемы заменить аллокатор, как таковой, в плюсах нет и если бы кто-то умел решать ту же задачу намного быстрее — все бы давно этим альтернативным аллокатором пользовались. Но на практике этого нет. Кастомные аллокаторы работают быстрее не потому что штатный медленный, а потому что они решают более простую задачу и благодаря учету ее специфики могут работать быстрее. Из более-менее универсальных аллокаторов которые при этом еще и быстрые мне вспоминается только интеловский аллокатор — он быстрее для многопоточных приложений, но расходует больше памяти.


        1. gandjustas
          08.09.2015 10:18
          -4

          Штатный аллокатор — страшный тормоз. Именно поэтому его заменяют
          Если бы это было не так, то никто бы не занимался подменой аллокаторов.


          1. 0serg
            08.09.2015 10:53
            +1

            Повторяю для тех кто не в состоянии прочитать комментарий еще раз: специализированные версии аллокаторов за счет использования специфики задачи или каких-то дополнительных компромиссов (например менее эффективного заполнения памяти) можно сделать быстрее. В основном игра стоит свеч только для тривиального случая «много одинаковых объектов». Но даже там какого-то невероятного прироста скорости нет.


            1. gandjustas
              08.09.2015 11:55
              -1

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


              1. 0serg
                08.09.2015 15:35
                +2

                А если бы в С++ была функция сделай_мне_хорошо() то на другие языки программирования никто бы и не смотрел. Ужасен язык где этой функции нет!

                Мне как-то сложно вести беседу с человеком который не видит разницы между тезисами «штатный аллокатор — страшный тормоз» и «использование специфики задачи позволяет в некоторых ситуациях выжать дополнительные 20-30% производительности за счет использования специализированного аллокатора».


            1. maaGames
              08.09.2015 15:46

              Тут вы чуточку не правы. malloc/new требуют перехода из user-mode в kernel-mode и из-за этого производительность страдает. Насколько страдает зависит от количества миллионов аллокаций (в секунду). Для new специфические аллокаторы и память могут гораздо эффективнее использовать. Но против malloc не приёма, если нет другого malloc.)


              1. 0xd34df00d
                08.09.2015 15:49

                Всегда ли? ЕМНИП реализации libc могут спокойно периодически запрашивать у ядра больше, чем надо, а потом отдавать память уже из этого пула.


                1. maaGames
                  08.09.2015 15:53
                  +2

                  Чуточку же.)
                  Я вообще только про Windows выше написал, так как не знаю тонкостей работы менеджера памяти linux…

                  Перефразирую, чтобы не было разночтений:
                  В зависимости от реализации менеджера памяти на конкретной версии ОС получение объекта из пула может быть эффективнее получения памяти под объект из менеджера памяти.

                  Отсюда возвращаемся к лейтмотиву всей трилогии статей и всех комментариев к ним: не посмотрев в профайлер вообще говорить не о чем.


                  1. 0xd34df00d
                    08.09.2015 15:57

                    Вот с последним абзацем вообще в любом случае трудно не согласиться :)


              1. 0serg
                09.09.2015 11:00

                Практически все менеджеры памяти работают в user-space.
                Применительно к винде malloc работает на основе HeapAlloc, а последний выделяет под кучу память большим куском через VirtualAlloc (который правит page table и потому требует kernel space) и работает дальше в user-space, обращаясь к VirtualAlloc только для выделения больших блоков памяти.
                Так что в винде malloc/new для блоков небольшого и среднего размера (<1 Mb примерно) как правило не требует перехода в kernel mode.


    1. gandjustas
      07.09.2015 23:53

      Не получается ли так, что Вы банально вынесли работу с GC за пределы измерения

      Вообще-то не вынес. За время каждого теста в C# происходит как минимум одна сборка мусора и она учитывается в общем времени забега.


      1. 0serg
        08.09.2015 08:37

        Ну она же очевидно не _весь_ мусор убирает (плюсы — весь)? Почему добавление GC.collect резко делает ситуацию намного хуже? Вы бы хотя бы график «время в зависимости от числа итераций» построили чтобы было видно когда происходит GC и сколько он занимает. И запустили бы тест, для объективности, на одноядерной машине, потому как «вычисления в одном потоке, GC во втором» — это шулерство, реальный вычислительно нагруженный код займет все ядра.

        Я бы предложил все же вписать GC.collect в конец теста, чтобы он вызывался _один_ раз а не сто, но это время было все-таки учтено.


    1. Mrrl
      08.09.2015 11:23
      +2

      Представьте себе квадратичный многочлен от N переменных, для которого сложение определено тривиальным образом, а умножение отбрасывает степени полинома выше второй… Ну и взять N=600

      А в какой задаче такое встречается? Может быть, и мне надо?

      Казалось бы… многочлен — массив длиной (N+1)*(N+2)/2, индекс монома определяется по паре индексов переменных. Перемножение — все коэффициенты каждого на свободный член другого плюс двойной цикл по линейным коэффициентам. Если много многочленов от небольшого числа переменных, то придётся добавить пару таблиц мэппинга переменных. Где тут мелкие объекты?


      1. 0serg
        08.09.2015 15:54
        +2

        Запись в виде плотной матрицы очень неэффективна, работа с несколькими матрицами 600x600, прямо скажем, не блистает быстродействием, а подавляющее большинство коэффициентов в этой матрице — нули. Эффективный код требует использовать одно из представлений разреженной матрицы и желательно — учитывать ее симметричность. Тут и возникают мелкие объекты переменной длины зависящей от степени заполнения матрицы.

        Возникает эта конструкция в оптимизационной задаче на поиск оптимального расположения N поверхностей друг относительно друга. Параметризуем расположение поверхностей 6(N-1) переменными, записываем функцию ошибки для заданного расположения, строим для этой функции разложение Тэйлора 2-го порядка — получается квадратичная функция аппроксимирующая функцию ошибки, у которой минимум ищется решением линейной системы уравнений. Минимизируем квадратичное приближение — это не дает точного ответа, но дает приближение к нему, после чего повторяем тот же процесс разложения в ряд Тейлора уже в новой точке


        1. Mrrl
          08.09.2015 16:07

          Ясно. Я поступаю так: завожу матрицу 6N*(6N+1) (одну), потом для каждой пары поверхностей (у меня это облака) строю форму ошибки для их расположения (это плотная матрица 12*13), потом прибавляю её элементы к нужным элементам большой матрицы. Ну и потом — метод Гаусса. Использовать разреженность большой матрицы пока не пытался, у меня N не очень большие (максимум, 20-30).


        1. encyclopedist
          08.09.2015 16:08

          Разреженные матрицы обычно все-таки хранят в форматах не использующих «мелкие массивы переменной длины», вроде CSR.
          Например в Eigen eigen.tuxfamily.org/dox-devel/group__TutorialSparse.html
          или в scipy docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.csr_matrix.html


          1. 0serg
            09.09.2015 11:56

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


        1. Mrrl
          08.09.2015 16:21

          И в терминах «ряда Тейлора» я над этой задачей не думал. Поступаю просто — записываю линейную часть сдвига точки в одном облаке, сдвига точки в другом, вычитаю одно из другого, прибавляю величину ошибки. Полученный линейный многочлен возвожу в квадрат, и все их складываю. Это для алгоритма «iterative closest point». Если бы подтягивал к касательной плоскости, поступал бы аналогично. То, что у сдвига сразу есть компоненты второго порядка, в голову как-то не приходило. Они действительно помогают?


          1. 0serg
            09.09.2015 12:41

            Насчет помогают ли — вопрос спорный, т.к. сразу сделали с компонентами второго порядка.
            Относительно старого подхода где поверхности позиционировались итеративно путем постепенного добавления +1 поверхности к уже поставленным N поверхностям он работает лучше :). А вот дают ли что-то компоненты второго порядка — не очень ясно. Теоретически могут, на практике толком не проверяли


            1. Mrrl
              09.09.2015 12:55

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


              1. 0serg
                13.09.2015 10:07

                Возможных вариантов много, мы не все пробовали, а текущий выглядит разумно эффективным :)


        1. Mrrl
          08.09.2015 16:49

          И просто из любопытства — каждая из поверхностей снимается неподвижным сканером, или сканер во время сканирования куда-то едет?


          1. 0serg
            09.09.2015 11:51

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


            1. Mrrl
              09.09.2015 12:06

              Понятно. Он триангуляционный?


              1. 0serg
                09.09.2015 12:37

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


                1. Mrrl
                  09.09.2015 12:53

                  Интересно. Нашёл парочку патентов, они используют специальные смещённые диафрагмы. Про вытаскивание глубины непосредственно из расфокусировки слышал лет 15 назад, но, по-моему, ничего из неё так и не сделали. Будет интересно почитать.
                  Сколько времени занимает реконструкция одного положения (без привязки)? И на каком процессоре?


                  1. 0serg
                    13.09.2015 10:43

                    Напрямую из расфокусировки тяжело что-то вытащить, но если добавить синхронизированную подсветку в плоскость фокусировки (по принципу конфокального микроскопа) и объектив с большой NA — то вполне реально. Дает очень высокую точность (20 микрон) и работает с полупрозрачными и бликующими объектами (мы сканируем зубы, так что для нас это важно, т.к. позволяет не покрывать зубы специальным порошком для сканирования).

                    Работает в реалтайме на не-топовом i7, латэнси первоначального (вполне приемлемого для визуализации) приближения <200 мс, а затем уже в менее жестких рамках нескольких секунд это приближении становится все точнее и лучше. Просто ведешь сканером и «открываешь» на экране поверхность.


  1. dom1n1k
    07.09.2015 23:34
    +4

    Жду третью статью, C# vs Java :)


    1. gandjustas
      07.09.2015 23:51
      -5

      А что мешает вам такую стать. написать?


  1. tangro
    08.09.2015 00:02
    +3

    Все эти «сравнения C++ и C#» заканчиваются в одном и том же месте: пойдите и предложите разработчикам драйверов, или ядер ОС, или движков баз данных, или браузеров, или ААА-игр, или протоколов, или видеокодеков использовать C#, ну потому что «почти так же по скорости, а писать удобнее». Дальше долго выслушивайте насмешки.


    1. withkittens
      08.09.2015 00:25
      +3

      пойдите и предложите
      ну потому что «почти так же по скорости, а писать удобнее».
      А где об этом почитать?

      Я лично вижу уже второй пост, который меряет время двух каких-то непонятных числодробилок, которые фактически вырождаются в замер скорости аллокации/сбора мусора, скорости работы памяти и работы оптимизирующих компиляторов. (И это помимо каких-то странных ограничений: «код на обоих языках максимально похожий» или «так пишут 9 из 10 программистов» (у автора явно накопилась большая статистика). На просьбы улучшить хотя бы то, что имеется — «ну форкай и напиши».)

      А где кто-то пытался с шарпом залезть в ядро и драйверы — не вижу.


      1. gandjustas
        08.09.2015 10:25

        Так что улучшить то?


        1. withkittens
          08.09.2015 13:24

          1, 2, 3 (таки 9 из 10 программистов не знают про std::swap?), 4.


          1. gandjustas
            08.09.2015 14:32

            Специально для вас сделал.
            .NET Native работает примерно с той же скоростью, что и C++.


    1. gandjustas
      08.09.2015 00:40
      +1

      На одного программиста баз данных и драйверов приходится от 100 до 1000 (навскидку) программистов, которые пишут прикладные программы.

      Если вы пишите драйверы, то у вас и вариантов мало, кроме C.


      1. tangro
        08.09.2015 10:25
        +2

        Смотря на статистику распространения C# и С++ по всяким разным рейтингам мы увидим одни и те же числа, ну, плюс/минус 30%, но уж никак не 1000х.


    1. lair
      08.09.2015 00:52
      +3

      или движков баз данных

      geteventstore.com
      ravendb.net


      1. tangro
        08.09.2015 10:25
        -1

        Ух, прям мейнстрим!


        1. lair
          08.09.2015 11:08

          Мейнстрим — понятие относительное, сегодня там одно, а завтра — совсем другое.

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


          1. tangro
            08.09.2015 15:07

            Мест, где небольшой вроде бы прирост производительности может существенно сэкономить байты\секунды\доллары тоже становится больше и кое-что наоборот с «почти такого же по скорости» переписывается на чём-то уровнем пониже, пример — habrahabr.ru/post/261205


            1. lair
              08.09.2015 15:38

              Мест, где небольшой вроде бы прирост производительности может существенно сэкономить байты\секунды\доллары тоже становится больше

              Это, на самом деле, очень интересный вопрос — становится ли таких мест больше в процентном отношении, или же нет.


    1. RPG
      08.09.2015 09:08
      +3

      В некоторых случаях в такие проекты не только шарперов на пушечный выстрел не подпускают, но и плюсовиков.


      1. 0xd34df00d
        08.09.2015 15:47

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


    1. bigfatbrowncat
      14.09.2015 23:19
      -1

      Unity видели? На нем довольно солидные игрушки делают.


      1. 0serg
        15.09.2015 00:00

        Выше уже приводили и пример и банальное контрзамечание что сам Unity на C++ написан


      1. Chaos_Optima
        15.09.2015 00:05

        Да неплохой двиг, а есть пример неплохого движка не на С++?


  1. xaoc80
    08.09.2015 02:42
    +6

    Когда-то я писал медиасервер и в тестах надо было вытянуть + одно full HD качество
    Оставим за скобками вопрос можно ли подобные вещи писать на C# (что бы при этом на 3-х ОС минимум работало)
    Но конкретно в этом проекте функции копирования памяти при преобразовании цветовых пространств удалось ускорить в разы
    Я развернул циклы, сделал так что бы эффективное использовался кэш
    А мой коллега добавил AVX инструкции там где это было необходимо
    Результат — мы это сделали
    Это банальный пример, но от этого он не становится менее «реальным» и «статистически» пригодным для Ваших рассужденй


  1. fareloz
    08.09.2015 13:39
    +4

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


  1. OlegMax
    08.09.2015 17:48

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


    1. lair
      08.09.2015 17:50
      +1

      При правильной реализации — нет, не будет.


  1. X_OSL
    08.09.2015 19:34

    Хотелось бы поблагодарить автора за статью и особенно пример на .NET Native, а также задать несколько вопросов:

    1. Удалось ли понять за счет чего .NET Native несколько медленнее С++, не получалось ли сравнить disassembly?
    2. Есть ли возможность использовать .NET Native с .Net Framework 4.0 (чтобы «разогнать» энтерпрайс, которому необходима поддержка XP:( )
    3. Какие видятся причины для того чтобы не переходить на .NET Native с обычного managed С#?


    1. X_OSL
      10.09.2015 09:03
      +1

      В качестве ответа на 2 и 3 самому себе:
      Похоже обычные десктопные приложения нельзя построить с .NET Native, а построить можно только приложения для Windows Store. Так ли это?


      1. fareloz
        10.09.2015 10:18

        Не знаток в такого рода деталях, но вроде даже в блоге Microsoft упоминалось, что данный момент так. Однако, вроде бы можно вручную с помощью какого-то инструмента скомпилиравать в Native (что не тоже самое, как минимум технология другая). Обычно это происходит автоматически для критических участков кода — система сама распознает. Но есть программы, вов ремя установки которых, установщик вызывает этот инструмент чтобы сразу все свои библиотеки скомпилировать под платформу.