Всем привет. Продолжаю серию статей про любимый язык программирования.
На этот раз коснёмся вечного вопроса "Java vs C++" в масштабах промышленного программирования.
Хотя некоторые вещи касаются вполне и выбора языка на ранних стадиях обучения, в том числе некоторые вещи применимы и для выбора языка для олимпиад. Я собственно так и выбрал Java :)
Самым авторитетным для меня источником стала статья моего тренера - Федора Владимировича Меньшикова. Эта статья как раз была и написана, когда встал вопрос "Что изучать после Pascal" :)
PS: Все копирайты соблюдены. Статья публикуется с разрешения автора.
Вы интересовались, какой язык лучше изучать - C++ или Ява. Я написал на
каждом из них десятки тысяч строк кода, поэтому попробую расписать
достоинства и недостатки каждого.
Небольшой обзор разницы идеологий языков далее.
Рассмотрим вопрос применимости языков для промышленного программирования -
создания программ в десятки и сотни тысяч строк кода.
Языки будем сравнивать по двум критериям:
1. Как известно, основное требование к программе - корректная работа.
Поэтому основным критерием сравнения будет "насколько язык располагает к
совершению ошибок."
2. Вторым фактором будет "насколько удобно писать на языке".
Критерий 1. Насколько язык располагает к совершению ошибок.
Ошибка 1.1. Обращение к чему-то несуществующему.
Когда происходит обращение к неизвестно чему, то и программа работает
неизвестно как. Скажем, в 255 случаях из 256 она может работать, а в 1
случае может сбоить. А ещё это "неизвестно что" может оказаться данными
другого модуля программы.
Ошибка 1.1.1. Обращение к несуществующему элементу массива.
Язык Ява, как и C#, гарантирует, что при индексации массива нельзя
обратиться к несуществующему элементу массива. Если обращение к
несуществующему элементу произошло, генерируется исключение.
Язык C++ унаследовал классические массивы от языка Си, а в языке Си
проверки при индексации массива не только отсутствуют, но и вообще
невозможны, поскольку в процедуры, например, не передаётся длина
обрабатываемого массива, только ссылка на его начало.
Однако C++ не заставляет пользоваться классическими массивами. На C++ можно
написать шаблон класса, имитирующего работу с массивом с проверкой
диапазонов. Всё различие будет заключаться в описании переменной:
StaticArray<int, 5> a;
вместо
int a[5];
а работа с таким "массивом" может происходить ровно тем же образом, как
работа с классическим массивом.
Я для себя такой шаблон написал, и подобные шаблоны используются в крупных
проектах, однако для чего-нибудь маленького вроде решения олимпиадной
задачи такой способ сделать язык безопасным не проходит - на написание
StaticArray никто не захочет тратить такое драгоценное на олимпиаде время.
Ошибка 1.1.2. Обращение к уже несуществующему объекту через указатель.
Язык Ява, как и C#, гарантирует, что объект не удаляется, пока к нему можно
обратиться через указатель. Поэтому обратиться к уже удалённому объекту
невозможно.
В языке C++ программист сам отвечает за удаление объектов, так что никто
ему не мешает создать два указателя на объект, через один указатель этот
объект удалить, а через второй потом поработать с тем местом, где объект лежал.
Однако C++ не заставляет пользоваться классическими указателями. В C++
можно написать шаблон класса, имитирующего указатель с проверкой отсутствия
обращений к объекту после его удаления. Ещё большую ценность представляет
класс так называемых "умных" указателей, которые сами удаляют объекты, на
которые указывают, как только исчезает последняя ссылка. Как и в случае с
массивами, всё различие в использовании такого шаблона будет в описании
переменной:
Ptr<MyClass> p;
вместо
MyClass *p;
Я в большом проекте использую такой шаблон, но для чего-нибудь маленького
вроде олимпиадных задач писать такой шаблон ну очень накладно.
Ошибка 1.1.3. Удаление объекта изнутри его самогО.
Как я уже упоминал, в Яве программист не может сам удалить объект, поэтому
проблемы нет. А в C++ программист сам отвечает за удаление объекта. Особый
случай - когда прямо или косвенно удаляется объект, в котором находится
исполнение. Проблема заключается в том, что после удаления объекта все его
поля являются недействительными, и после удаления самого себя нужно строго
выйти из процедуры, ни к чему больше не притрагиваясь. Как правило это не
так просто, если не знаешь, что ты себя удалил. Решением является в том
объекте, который провоцирует удаление, проверять, не в удаляемом ли объекте
сейчас находится поток управления. Решение работает, но такие проверки -
это, конечно, дополнительные усилия со стороны программиста.
Ошибка 1.2. Использование неинициализированных переменных.
Как в случае с обращением к неизвестно чему (1.1.1) можно получить
неизвестно какой результат, так и в случае обращения к переменной, в
которую значение не было занесено заранее, ничего хорошего ждать не приходится.
В Яве, как и в C#, гарантируется, что все поля объекта при создании
зануляются. Если это int - значение 0, если boolean - false, если объект -
null.
В C++ зануления нет, и это очень опасно. Реально сталкивался с проблемой
невоспроизводимых ошибок. При одном состоянии памяти программа переходит в
состояние ошибки, при другом состоянии памяти замечательно работает. Ошибка
оказалась в отсутствии инициализации поля в одном (!) из двух конструкторов.
Однако в C++ есть возможность переопределить операцию new, так что она
будет не только выделять память, но и занулять место под динамической
переменной. В моём проекте на C++ все классы унаследованы от класса с таким
переопределённым оператором new.
Как и в случае с прочими упоминавшимися возможностями, написание такого
переопределения оператора new дело не совсем тривиальное, и в маленьких
проектах вроде олимпиадных задач нет возможности тратить на это время.
Ошибка 1.3. Отсутствие удаления/закрытия ресурса.
Если по предыдущим пунктам могло сложиться впечатление, что Ява намного
лучше C++, то этот пункт будет скорее в пользу C++.
Как выглядят внутренности обычной процедуры обработки файла:
<открыть файл>
<читать и обрабатывать данные>
<закрыть файл>
Пока последовательность действий линейна, всё хорошо, открытый файл будет
закрыт. Но что если в ходе обработки файла случится исключение или будет
желание выйти через return из функции? Будет ли файл корректно закрыт?
В Яве для гарантированного закрытия таких ресурсов приходится операторы
<читать и обрабатывать данные> заключать в блок try-finally. На самом деле
не очень эстетично выглядит, а уж когда несколько переменных таким образом
гарантированно закрыть надо - тут уже синтаксис получается туши свет. И что
самое противное - ничто не обязывает программиста писать блок finally, так
что ничто не поддерживает систему гарантированного освобождения ресурсов.
В C++ в смысле освобождения ресурсов всё, наоборот, хорошо. Язык
гарантирует вызов деструкторов всех локальных объектов при выходе из
процедуры любым способом - и через return, и через исключение. Поэтому всё,
что нужно - это обернуть ресурс в объект, и в конструкторе объекта
прописать открытие ресурса, а в деструкторе - закрытие. И в тексте основной
процедуры не появляется никаких finally, и где бы этот объект не
использовался, везде при любых обстоятельствах освобождение ресурса
гарантируется.
Ошибка 1.4. Неожиданные для программиста свойства языка.
Язык C++ имеет ряд особенностей, из-за которых программы могут работать не
так, как ожидает программист, а чтобы они работали как надо нужно что-то
неочевидное изменить. Такие особенности просто нужно знать и учитывать.
Проблема в том, что люди, начинающие писать на C++, этих особенностей не
знают, и узнаЮт об этих граблях только через некоторое время. Существуют
даже книжки о таких граблях. Мне нравится книга Скотта Мейерса (он же
Майерс, он же Мэйерс) "Эффективное использование C++".
В Яве таких особенностей практически нет. С одним похожим случаем я
столкнулся только при использовании одного класса стандартной библиотеки, а
в C++ таких особенностей десяток в самОм языке.
Критерий 2. Насколько удобно писать на языке.
Возможность 2.1. Циклический импорт.
Иногда два класса зависят друг от друга. В компиляторе может быть, скажем,
такая ситуация: в выражении (скажем, при приведении к какому-то типу) может
встречаться тип, а в типе (скажем, в описании диапазона индексов массива)
может встречаться выражение. Первый должен вызвать методы второго, а второй
- методы первого. Возникает вопрос, кто кого должен импортировать.
В Яве этот вопрос решается просто - циклический импорт разрешён, классы
друг друга увидят. В C++ циклический импорт запрещён, кого-то нужно
объявлять первым. Решение на C++, конечно же, существует и заключается в
наследовании от интерфейсного класса с чисто виртуальными функциями, но как
заумно это звучит, так же плохо это и выглядит, хотя замечательно работает.
Возможность 2.2. Библиотеки шаблонов структур данных.
Как C++, так и Ява, в отличие от Паскаля, оба содержат библиотеки с
шаблонами вроде std::vector, std::map и т.п. Например, std::map - это
аналог массива, только индексы не обязаны быть целыми числами, достаточно
уметь сравнивать две переменные типа ключа на меньше. Эффективная
реализация подобных структур данных для каждого конкретного случая
потребовала бы от программиста титанических усилий - а тут всё уже готово,
бери и пользуйся.
К сожалению, стандартные контейнеры C++ поступают в духе Си и не
обеспечивают никаких проверок диапазонов и т.п. К счастью, существует
бесплатно распространяемая библиотека STLPort, где можно включить режим
проверок. Но её нужно скачивать и устанавливать, с известными компиляторами
она не поставляется.
А ещё очень хочется оторвать руки тому, кто в C++ у std::vector (массив с
возможностью роста) значение функции size() сделал беззнаковым числом.
После этого цикл
for (int i = 0; i < a.size(); i++)
приходится записывать или как
for (int i = 0; i < (int)a.size(); i++)
или как
for (std::vector<int>::size_type i = 0; i < a.size(); i++)
или получать предупреждение компилятора о сравнении числа со знаком и числа
без знака.
Возможность 2.3. Исключения.
Как C++, так и Ява, в отличие от Оберона, оба поддерживают исключения.
Что должен сделать компилятор при обнаружении ошибки? Сообщить о ней - и на
этом в принципе миссия завершена. Традиционный подход в простеньком
компиляторе - после выдачи ошибки просто завершить программу с помощью
средств вроде exit() C++, System.exit() Явы или halt() Паскаля. А что если
компилятор встроен в редактор? Всё-то он не должен выносить, должна
завершиться только стадия компиляции. Вот тут как раз исключения и могут
помочь. Они позволяют из процедуры выдачи ошибки перескочить на самый
верхний уровень без дополнительного кода в процедурах синтаксического
анализа. Помнится, я писал компилятор на Обероне, так там раз 200 в
синтаксическом анализаторе встречалась строка IF error THEN EXIT; END; Вот
какие ужасы могут твориться в языке без поддержки исключений.
Вот краткий обзор возможностей языков. В плане обеспечения надёжности для
больших проектов C++ и Ява практически равны. Для надёжных набольших
проектов Ява, похоже, подходит лучше. А для тех, кто считает, что пишет
только правильные программы, в которых нет ошибок и которые не нуждаются в
отладке, безусловно, подходит "чистый" C++. :-)
PS:
Прошу не оценивать данную статью, ибо за её качество ответственность несёт сам автор.
Я не имею никакого права получать за неё + или - ,т.к. она не моя.
Лично мне она понравилась, считаю её весьма ценной и выложил исключительно для того, чтобы народ смог оценить кое-какие грани рассматриваемых языков и сделать нужный выбор.
Я с Java увы не знаком, "промышленное" ПО пишу на C#, а олимпиады на С++. Но речь не об этом.
Чтобы писать промышленное ПО на С++ нужно иметь опыт.. и очень неплохой опыт. И знать множество граблей, на которые наступать нельзя. На работе есть товарищ, который как раз пишет довольно серьезные вещи на С++. Он выдвинул идею о том, что можно писать все на чистом С. И даже то, что С не поддерживает ООП как таковое, его не страшит. Главный довод в том, что граблей намного меньше и все плюшки, которые дает Объектноориентированный подход можно самому обеспечить. Мне сложно с этим согласиться.
Поэтому интересно есть ли из участников люди, которые разделяют любовь к обычному С в промышленной разработке?
Интересная статья. Но, если я не ошибаюсь, в STL как раз предусмотрена проверка выхода за границы. Я много раз видел исключение "vector(string) subscript out of range".
По поводу разверов в unsigned int, то да, борода. Однако строчка
#define sz(v) (int((v).size()))
полностью решает эту проблему.
Можно делать так: for (size_t i = 0; i < a.size(); i++) И это решает проблему, не теряя смысла.
Я уже подумываю — а не убрать ли мне сей пост в черновики... Года не проходит, как его обязательно кто то "воскресит"...
Зачем убирать в черновики такой хороший пост?
Когда писался этот пост сайт только начинал расти, я чувствовал, что могу быть чем то полезен. Но в результате огрёб столько не приятных эмоций (и всё по делу), что вспоминать стыдно. Прям как смотришь на свои программы, которые писал 5-6 лет назад :-)
Если пост даже с моими подчас дерзкими комментариями всё ещё может быть полезен (как минимум комментариями других людей), то можно и не убирать.
Думаю, что пост все еще полезен :)...Я вот узнал некоторые интересные вещи, прочитав его и комментарии к нему.
Вот ответ из письма-ответа на некоторые комментарии. Автор предупредил, что больше отвечать не будет.
Но, если я не ошибаюсь, в STL как раз предусмотрена проверка выхода за
границы. Я много раз видел исключение "vector(string) subscript out of range".
Ошибаетесь. В Стандарте описано, когда производится проверка и выдача исключения std::range_error. Никогда при применении []. У строк - скажем, в случае substr(). У векторов - в случае at().
По поводу разверов в unsigned int, то да, борода. Однако строчка #define sz(v) (int((v).size()))
полностью решает эту проблему.
Это для олимпиад такое решение подходит. А если в языке int 32-разрядный, а указатели 64-разрядные?..
1) Заголовок статьи совершенно не соответствует содержанию. Предлагаю
"Java vs C++ для олимпиадного программирования".
Как раз программу в 100 (пусть и в 500) строк можно держать в голове и написать идеально. Написание программы в 100 тыс строк без проверок, встроенных в язык/библиотеки требует колоссальных усилий. Я бы не хотел писать на Perl ничего свыше 1000 строк.
3) StaticArray писать не надо. Есть готовый boost::array. А на самом
деле std::vector подходит почти всегда. Но это только в "промышленном"
программировании.
std::vector не подходит по причине отсутствия проверок диапазонов. boost::array тоже - разрабатывался прежде всего из соображений скорости. Так что когда нужен аналог проверок при каждом обращении к массиву (как в Яве) - приходится писать своё.
4) Времена жизни объектов надо знать. И создавать объекты в строгих
иерархиях времён жизни. Для некоторых особо сложных случаев есть
boost::shared_ptr.
Особенно круто boost::shared_ptr помогает в засорении динамической памяти в случае циклических ссылок.
6) Все типы, кроме элементарных правильно себя инициализируют. Если у Вас
слишком часто используются элементарные типы в "промышленных" условиях,
ищи по теме "одержимость элементарными типами".
class Class {
int field;
};
Кто проинициализирует поле field? Никто! Нужно не забыть в каждом конструкторе! Или Вы предлагаете вместо int использовать обёртку - класс, содержащий одно поле типа int?
9) Про "циклический импорт" см
http://alexanderchuranov.com/cc-examples/circular/ и никаких наследований.
А если тело функции хочется прямо в описании класса написать?
10) Какой из стандартных контейнеров не может проверить индекс или ключ?
Для vector, deque есть метод at(), для set, multiset, map, multimap - find,
хотя в (multi)map и [] сработает отлично.
Вы когда-нибудь видели at() в программах? Я - нет. Всегда только []. А у него проверок нет! Для set и map [] _не_ сработает отлично - создаст новый элемент со значением по умолчанию. А это далеко не всегда то, чего хочется. Да, find есть, но опять же выдаст не ошибку, а итератор map.end().
11) "А ещё очень" хочелось бы "оторвать руки тому", кто бы сделал
std::vector<char>::size_type знаковым числом. Тогда на x86-32 сделать
массив байт больше 2Гб не получилось бы.
Правильно. Из-за горстки тех, у кого 4 Гб памяти и архитектура x86-32 должны страдать миллионы других программистов!
Надеюсь, в этот раз получилось справиться с "местным форматированием".
Однако, ответы Федора на комменты, выложенные тобой, меня просто потрясли - уровень а**енности зашкаливает - нам всем нужно к этому стремиться. Респект Федору, однозначно.
плюспицот).
А вообще, когда выкладываешь что-то, можно воспользоваться средствами форматирования)) жирным текстом где-нибудь сделать или курсивом важные пункты) а у тебя все одна каша
http://en.wikipedia.org/wiki/C%2B%2B0x
http://www2.research.att.com/~bs/C++0xFAQ.html
По какой-то причине автор одним из главных зол С++ выбрал отсутствие проверок в operator[] у массивов и стандартных контейнеров. Ну, с массивами допустим все в общем-то верно (хотя постоянное использование голых статических массивов вроде бы не сильно мешает многим победителям различных олимпиад), но претензии к вектору мне не совсем понятны.
Оно то, конечно может и да, но давайте на практике попробуем не инициализировать переменную, например в VC++ 2005. Итак пишем код: Компилируем, видим: warning C4700: uninitialized local variable 'i' used. Предположим, что мы не смотрим на ворнинги (запомните это предположение). Запускаем в дебаге.. ой, что это: Run-Time Check Failure #3 - The variable 'i' is being used without being defined.
С этим я в общем-то согласен. Если недостаточно хорошо знать С++, можно иногда нарваться на неприятности даже в олимпиадах и это, наверное, основная проблема.
Если хочешь использовать современные редактор кода с подсветкой, динамическим хелпом и т.п. - могу предложить использовать Eclipse . Версии Classic 3.5.1 (162 MB) вполне должно хватить. Более того, используя плагины можно расширить его функциональность. К примеру я сейчас под ним же пишу Java Servlet и управляю деятельностью сервера Tomcat. Нашумевший NetBeans не стал бы рекомендовать, ибо это куда более "тяжелый монстр" да и зачем "использовать экскаватор, чтобы вырыть ямку для саженца" :)
Ну если ты не хочешь замарачиваться на какие то IDE - Блокнот тебе в руки. Многим этого хватает :)
Ну да. Незабудь поставить себе JRE и JDK последних версий :)
FAR с колорером и блокнот - слегка разные вещи, помни об этом. И действительно, хочу посмотреть на человеков, что пишут в блокноте :)))
+1. Именно про таких "крутых кодеров" я и говорил, которым не нужны всякие рюшечки IDE.
А "блокнот" - так это метафора (забыл в кавычки выделить).
Теперь я знаю 3-их хардкорных кодеров :)
Но старый добрый Паскаль никогда не подводит,так как ты пишешь всё сам :) Что иногда очень превышает по времени программы СТЛ :)
Генка стал чемпионом мира :) И он на паскале фигачил :D
А вектор-то чем не угодил? Перформанс? А если перформанс - краеугольный камень, то о каком сравнении с явой вообще идет речь? :о
> К сожалению, стандартные контейнеры C++ поступают в духе Си и не
обеспечивают никаких проверок диапазонов
В дебаге все проверки есть. В ретейле их и не должно быть, ибо перформанс.
В целом я думаю любая статья в этом духе будет нубской. Потому что заголовок нубский. Термин "Промышленное программирование" по-моему придумали олимпиадники, которые пытаются оправдать свое занятие. Только от этого занятие олимпиадными задачами не перестало быть никак не относящимся к этому "промышленному программированию" занятием :о) Вам никогда в жизни не пригодится знание как написать максимальный поток минимальной стоимости, потому что когда реально такая задача перед вами встанет, у вас не будет ресурсов на поток, вам нужно будеть писать эвристику. Олимпиадки - это хобби. Это забавно, на это можно потратить пять лет жизни в ВУЗе, потому что вы еще не зависимы и у вас есть это время, олимпиадки даже могут принести желанную регалию, которая потом в вашем резюме будет сверкать ярче солнца и гиганты индустрии будут звать вас (это же наша цель, верно? но медалей каждый год 12, а нас тысячи...)
Кстати, кто-то мне говорил, что все наши легендарные АСМ-дядьки, которые пошли потом в большое Г, не очень-то там и аутперформят.
Вернемся к статье. Если кто-то поработал годик на двух языках, он не стал экспертом в них :о) Я пять лет пишу на PHP, и только последний мой проект занимает 32 тысячи строк, но я нуб в ПХП. Количество строк и количество лет не всегда о чем-то говорит.
Большие программные комплексы все равно будут писаться на С++, потому что там важна скорость. И как бы не росла мощность компьютеров, написание их на Java не станет worth doing.
Вообще поразительно, что сравнивается C++ и Java, а не С++ и C#. Что, реально сегодня в индустрии много пишут на Java? В моем Ижевске основные предложения о работе были на .NET (я выкидываю 1С из рассматриваемого списка :о)). Даже epam, который так славится тем, что "они работают на всем" (господи, они даже писали на J#) в Ижевске не имел позиций для тех, кто кодячит на Java.
И хваленая кроссплатформенность Явы работает очень подозрительно. Проект, написанный под Windows очень сильно не хотел отображать русский текст, будучи развернутым на FreeBSD. Все исходники при этом честно были сохранены в UTF-8. На сервере с рутовыми правами шаманство помогло этого избежать, на сервере без рутовых прав все было тщетно, никакие ключи компиляции не спасали. При этом полностью переписанная кодяка на C++ перенеслась с лету, пришлось только дважды написать весь код для соккетов и потоков - но в данном случае это было worth doing. Да и кому нужна сегодня эта кросс-платформенность :о) Бывает нужно либо чтобы работало под Windows, либо чтобы работало под *-nix. Приведите мне пример, когда ни жить ни быть надо чтобы работало и там и там.
А вообще, когда я после олимпиадок попал в необходимость работать на дядю, я быстро для себя понял, что знания языка не важно. Вы не умеете писать на C#? Вы научитесь делать это за месяц. То, чему вы не научитесь за месяц, никому нафиг не надо :о) А как минимум месяц на то, чтобы понять, как корпорация, в которую вы попали, работает, вам все равно будет нужен.
А если фирма работает на Java, то даже если у вас есть миллиард доводов, что С++ лучше, вам придется писать на Java - мало кто спросит какой язык вам удобнее :о)
Во многом не согласен с автором.
StaticArray у автора всплыл как реализация safe-массива. Вы пишите, что в дебаге все проверки есть. Это о какой-то конкретной версии C++ от Microsoft? Поверьте, не все пишут на Microsoft Visual Studio последних версий. Более того, кажется, это касается только вектора, в то время как статические массивы остались обделены вниманием такой строгой проверки. Кстати, что такое "ретейл" - розничная продажа?
Я не думаю, что термин "Промышленное программирование" придумали олимпиадники. Google дает свыше 300 тысяч ссылок. Да и вроде бы понятно, что это русский перевод английского enterprise.
"Вам никогда в жизни не пригодится знание как написать максимальный поток" - ну не надо так категорично высказываться. Задачи бывают разные. Теория потоков имеет большие приложения - погуглите и найдете примеры. Конечно, если под программированием понимать исключительно написание систем документооборота, электронных магазинов, то да, вы правы.
По поводу "не очень-то там и аутперформят" (правда, я не понял где): у меня достаточно обратных примеров. Если и говорить, что олимпиады это хобби, то хобби очень полезное и нужное. Как минимум техника программирования и умение размышлять будут многократно востребованы. А если еще из командных олимпиад вы вынесите понимание что такое команда, и как ей управлять, чтобы она лучше работала, умение элементарно общаться с людьми и доходчиво объяснять свои мысли, то вам цены не будет.
"Большие программные комплексы все равно будут писаться на С++", "Что, реально сегодня в индустрии много пишут на Java?" Ижевск не столица силиконовой долины. Посмотрите статистику, например, здесь или здесь.
По поводу кроссплатформенности Java - может вы ее просто готовить не умеете? "Приведите мне пример, когда ни жить ни быть надо чтобы работало и там и там." Например, разработка любого standalone приложения (хороший пример - IDE, и на Java их очень даже пишут: Eclipse, Intellij IDEA).
По поводу не принципиальности знания языка это правда лишь отчасти. Например, если вы руководите разработкой серьезного приложения - вам надо очень хорошо ориентироваться в технологиях вокруг данного языка или платформы.
Было бы кстати клево, если бы можно было редактировать свой комментарий. Мысли не всегда с первого раза удается выразить верно :о)
Почему я сказал именно про Ижевск при сравнении предложений на Java и C# (помимо очевидной причины - я больше ни о чем и не знаю) - потому что понятно, Ижевск - такой же город, как и большинство городов России, за исключением столиц и может еще пары особо крутых мегаполисов, и предложения работы в целом должны быть похожи. Я не спорю, что Java может быть популярна overall (я не берусь сейчас судить bias у приведенной статистики) - у меня нет никаких зацепок чтобы сложить свое мнение, я говорю, что в моей провинции предложений на .NET было больше, чем на Java, причем значительно больше. Отсюда я делаю предположение, что в большинстве провинциальных городов России это так. А так как многие после ВУЗа и АСМ останутся в родном городе, то для них скорее встанет вопрос о том, что сейчас в их родном городе нужнее.
Но это не интересная тема - я абсолютно согласен, что использовать маленький город для выводов о целой стране не верно.
Интереснее тема - это насколько полезны олимпиадки. Это вообще можно вынести в отдельную тему, сейчас так и сделаю :о Уверен, что многим из тех, кто сейчас только готовится к своим большим стартам, будет интересно, как сейчас дела у тех, кто уже откатал свое..
> Например, если вы руководите разработкой серьезного приложения - вам надо очень хорошо ориентироваться в технологиях вокруг данного языка или платформы.
Ну опять же, я смотрел с точки зрения человека, который только закончил ВУЗ и идет на работу. Основной опыт и придет как раз на работе - имхо. К тому времени как карьерная лестница доведет до руководства проектом опыта уже будет вполне достаточно.
>Большие программные комплексы все равно будут писаться на С++, потому что там важна скорость. И как бы не росла мощность компьютеров, написание их на Java не станет worth doing.
>А вообще, когда я после олимпиадок попал в необходимость работать на дядю, я быстро для себя понял, что знания языка не важно. Вы не умеете писать на C#? Вы научитесь делать это за месяц. То, чему вы не научитесь за месяц, никому нафиг не надо :о)
>А если фирма работает на Java, то даже если у вас есть миллиард доводов, что С++ лучше, вам придется писать на Java - мало кто спросит какой язык вам удобнее :о)
Взаимоисключающие строки...
А зачем мне идти на работу в компанию, которая меня не устраивает?
Далекое от реальности мнение, если честно. Инструмент нужно выбирать, исходя из требований. А требования зачастую вообще экономические.
>А вектор-то чем не угодил? Перформанс?
Шаблонный тип вроде вышеприведенного несет информацию о типе -- часто это бывает полезно (позволяет отсеять некоторые ошибки при компиляции и/или перегрузить функцию для массивов разной длины). Ну и оверхэд по памяти нулевой (что актуально для мелких массивов).
Я кстати нубский вопрос возможно задам, а что, реально можно не тип данных а число в шаблоне указывать? :о
Да. Можно даже подсчитать факториал в compile-time. Сделать таблицу этих факториалов (пока, по крайней мере) нельзя.
http://en.wikipedia.org/wiki/Template_metaprogramming
Статью писал немного ламер.
Во-первых С++ и Java по производительности немного, эээ, разного уровня языки.
За переопределение new/delete конечно, руки надо оторвать и выбросить сразу. Если нет ума написать свой макрос и ПОЛЬЗОВАТЬ только его, в С++ делать нечего. Захотим мы подключить стороннюю либу, где такой же семипядный программер уже переопределил эти операторы под свой аллокатор - все пиши пропало, херачь проект заново.
про int'овый size() - я чуть не описалсо... Для STL контейнеров есть BOOST_FOREACH, для массива прокатит проверка в духе:
const size_t length = (длина массива);
for( size_t index = 0; index != length; ++index);
Если написано < или постфиксный оператор - программера надо гнать за парту.
Сам я кстати нигде не учился (не смог попасть на бюджетные места в 99 - все уже купили до нас) - но прочел книжек 30 по С++ (Мейерс - редкое УГ, Саттер/Вандервурд рулит) в итоге рабатываю строителем, и пишу программы походу качеством повыше чем Вы. С уважением, пряморукий строитель.
for (int i = 0; i < n; i++)
то меня "надо гнать за парту"?
Не поленился, посмотрел ассемблерный код после C++ Builder.
Что
for (int i = 0; i < n; i++)
что
for (int i = 0; i != n; ++i)
инкремент и проверка условия делается за 3 маш.команды.
И в чем-то более сложном, типа
a[++j + k + 1] = 10;
a[j++ + k + 2] = 10;
одинаково по 4 маш.команды.
Может для другого компилятора или для более сложных выражений это не так, но я сложных выражений с оператором ++ и не пишу, чтобы на какие-то побочные эффекты не нарваться.
Так что "гнать за парту" пусть останется на совести автора.
Розовые очки сними.
А Вы со своим вопросом можете обратиться к Елене Новиковой, если она до сих пор преподает в УдГУ, как оно там было в то время на поступлениях ;).
Мне лично она тогда задала больше десяти дополнительных вопросов вместо полагавшихся двух-трёх и нашла-таки пробел в моих школьных познаниях. Кто ж виноват, что разложение числа e в ряд Тейлора в школьную программу не входит до сих пор?
vector<int> v;
for (int i=0; i<v.size()-1; ++i) ...
перестает работать на пустом векторе. А работа с размерами вектора около нуля во много раз более частая, чем с гигантским размером ради которого нужен беззнаковый тип.
Все эти варианты развалятся на куски с вектором, размер которого превышает 5 миллиардов, на 64-ех битной машине.
Случай крайний, но в общем случае в таком контексте пишется size_t, а не unsigned или int.
Звучала статья как с++ фигня, а гава паинька. Мне лично понравилась статья про фабрику фабрик(по поводу гавы, вчасности) на хабре. Спасибо автору за книгу Мейерса!
Пахнет холиваром).
а некропостингом просто воняет