Что нужно при изучении C++, если я пришел с PHP/Java?
Мне нужно изучить C++, чтобы научиться создавать приложения Nokia WRT и / или maemo. Мне нужно знать, что надо и какие аспекты C++ мне нужно / нужно учить или больше фокусироваться. Я вспомнил одну вещь: в C++ нет сборщика мусора. Поэтому мне нужно сосредоточиться на типе переменной. Но есть ли другие действительно важные, и я не могу это игнорировать?
6 ответов
Основная проблема заключается в том, чтобы попытаться представить C++ с точки зрения его отличия от PHP или Java.
Извините, просто так не работает. С ++ отличается от этих языков почти во всех важных отношениях, кроме синтаксиса арифметики. Иногда различия неуловимы. Вы должны изучить его по-новому и не думать, что что-то, что подходит для PHP или Java, будет хорошо работать для вас в C++.
Тем не менее, общие трудности включают в себя:
- управление ресурсами: RAII; реализация конструкторов копирования, деструкторов и
operator=
; избегая необходимости реализовывать копирование ctors, dtors, operator=. - понимание, что такое ссылки, указатели, значения и автоматические переменные.
- избегать неопределенного поведения (
myarray[i] = i++;
это любимый). PHP и Java являются более "жестко" определенными языками, чем C++: во-первых, поведение программы, скорее всего, будет определено и, следовательно, надежно. Из-за этого отдельные реализации более похожи на реализации C++. Довольно легко написать программу на C++, которая не просто делает неправильные вещи, она делает совершенно разные вещи при разных запусках, включая аварийное завершение, повреждение данных и т. Д. - научиться безопасно и эффективно использовать шаблоны, множественное наследование, перегрузку операторов и другие функции, с которыми вы не знакомы.
- правильные идиомы для создания и перехвата исключений (выброс по значению, перехват по ссылке, не выбрасывать из деструктора).
- написание переносимого кода (понимание различия между тем, что гарантирует стандарт, и тем, что не гарантируется, но тем, что ваша реализация делает. Поведение, определяемое реализацией, например, размерами фундаментальных типов).
- Стандартные библиотеки C++ ограничены по сравнению с Java или PHP. Вы будете использовать нестандартные библиотеки. Например, Maemo использует GTK+ и / или Qt. Часто ответ "как я могу сделать X в C++" таков: "вы не можете сделать это, используя только стандартный C++, вам нужны API-интерфейсы для конкретной платформы или переносимая библиотека, скомпилированная для вашей системы". X может быть графикой, сокетами, регулярными выражениями, многопоточностью, обработкой XML, шифрованием. Особенно с мобильными платформами вам нужно следить за версиями ОС, вещи могут меняться и будут меняться под вами время от времени.
Научитесь использовать контейнеры STL прямо сейчас. Хотя синтаксис итератора не подходит для людей, пришедших с других языков, он предоставляет вам встроенные структуры данных, которые вы обычно используете в коллекциях Java или PHP как встроенные (карты / хэши, списки, стеки, векторы) без написания прикольного кода указателя с динамическим распределением, которое так часто отвлекает новичков от необходимости изобретать велосипед и связываться с ошибками памяти.
Кроме того, если вы пишете код, специфичный для платформы (например, приложение Qt или Microsoft MFC), вы часто будете видеть примеры использования контейнеров, специфичных для фреймворка, где STL был бы более разумным выбором. STL (и Boost) могут заполнить пробелы. Использование инфраструктуры GUI не означает, что вы должны использовать все, что предлагает среда. Держитесь подальше от нестандартных контейнеров, если вы не знаете, без тени сомнения, вы никогда не будете переносить программу или повторно использовать части кода.
Одна ошибка, которую я видел у некоторых Java-программистов, когда переход на C++ вызывает утечку памяти. Например:
try {
myType pVar = new myType();
DoSomething(pVar);
delete pVar;
}
catch (exception) {
cout << "Doh! Something failed!" << endl;
}
В приведенном выше случае, если метод DoSomething() выдает исключение, pVar никогда не будет удален, что приведет к утечке памяти.
(Решения для этого включают: объявление всех переменных перед блокировками try/catch, использование auto_ptr или просто избегание try-catch для начала!)
Я бы сказал, что это не переменный тип, а только то, что вы очищаете свою память. Java очистит вашу память, но C++ не сделает это за вас. В противном случае управление вашими ресурсами при наличии исключений очень важно.
С положительной стороны, вы получите то, что они называют "детерминистическим завершением". Огромная выгода. Посмотрите, как аббревиатура "RAII". Я думаю, что это, возможно, одна из самых важных идиом в C++.
Это означает "Получение ресурсов - Инициализация", но на самом деле это означает "Когда этот деструктор сработает, я уберу за тобой даже при наличии исключений". На практике это означает, что любой объект, который вы создаете или открываете, который вам нужно закрыть или удалить, вы можете удерживать с помощью умного указателя. Умный указатель будет убирать за вами. Это очень, очень сильно, когда вы понимаете это и начинаете использовать его. Это делает вашу проверку ошибок, обработку исключений и код очистки ресурсов очень простой.
Самая важная вещь (на мой взгляд) состоит в том, что все является типом значения, поэтому, если вы передаете массив в функцию, подобную этой:
void do_stuff(std::vector<int> my_array)
{
...
}
тогда my_array
то, что передано, является копией указанного аргумента. Подобное копирование всего массива стоит дорого, поэтому в общем случае вы хотите передать по const-reference:
void do_stuff(const std::vector<int>& my_array)
{
...
}
(Примечание: опустите const
если вы хотите изменить оригинал my_array
).
Мне любопытно, почему "PHP/Java" здесь рассматривается как одна вещь. Это не так.
- Переход Java->C++ довольно большой, но он выполнимый, вам просто нужно изучить много дополнительного синтаксиса, несколько дополнительных понятий, таких как деструкторы, конструкторы копирования, срезы объектов и перегрузки операторов, и прийти к соглашению с библиотекой C++,
- Переход PHP->C++, с другой стороны, еще на порядок больше, так как он касается (а) очень плохо определенного исходного языка, (б) языка, основанного на шаблонах, а не на классах, и (в)) язык, который исполняется в особой среде.