Подтвердить что ты не робот

Каковы часто неправильно понимаемые концепции на С++?

Каковы часто непонятые понятия в С++?

4b9b3361

Ответ 1

С++ не является C с классами!

И нет языка C/С++. Все идет вниз.

Ответ 2

У С++ есть автоматическое управление ресурсами.

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

Пример: (Сделано с составленным API, потому что у меня нет времени проверить документы сейчас)

// C++
void DoSomething()
{
  File file("/tmp/dosomething", "rb");
  ... do stuff with file...
  // file is automatically free'ed and closed.
}

// C#
public void DoSomething()
{
  File file = new File("/tmp/dosomething", "rb");
  ... do stuff with file...

  // file is NOT automatically closed.
  // What if the caller calls DoSomething() in a tight loop?
  // C# requires you to be aware of the implementation of the File class
  // and forces you to accommodate, thus voiding implementation-hiding
  // principles.
  // Approaches may include:
  // 1) Utilizing the IDisposable pattern.
  // 2) Utilizing try-finally guards, which quickly gets messy.
  // 3) The nagging doubt that you've forgotten something /somewhere/ in your
  //    1 million loc project.
  // 4) The realization that point #3 can not be fixed by fixing the File
  //    class.
}

Ответ 3

Свободные функции неплохие, потому что они не входят в класс. С++ не является языком ООП, но основывается на целом ряде методов.

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

Это также отражается в языке: цикл, основанный на диапазоне для C++0x (следующая версия С++, выпущенная очень скоро) будет основана на бесплатных вызовах функций. Он получит начальные/конечные итераторы, вызвав бесплатные функции begin и end.

Ответ 4

Разница между назначением и инициализацией:

string s = "foo";    // initialisation
s = "bar";           // assignment

Инициализация всегда использует конструкторы, назначение всегда использует operator =

Ответ 5

В порядке убывания:

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

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

Ответ 6

Самая пагубная концепция, которую я видел, заключается в том, что ее следует рассматривать как C с некоторыми аддонами. На самом деле, с современными С++-системами, его следует рассматривать как другой язык, и большая часть С++-bashing, которую я вижу, основана на модели "C с надстройками".

Чтобы указать на некоторые проблемы:

Хотя вам, вероятно, нужно знать разницу между delete и delete[], вы, как правило, не должны писать. Используйте интеллектуальные указатели и std::vector<>.

Фактически, вы должны использовать * только редко. Используйте std::string для строк. (Да, это плохо спроектировано. Используйте его в любом случае.)

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

В общем, члены данных класса не должны быть непосредственно видимыми либо путем public, либо с помощью геттеров и сеттеров. Существуют исключения (такие как x и y в точечном классе), но они являются исключениями и должны рассматриваться как таковые.

И большой: нет такого языка, как C/С++. Можно писать программы, которые могут быть скомпилированы надлежащим образом на любом языке, но такие программы не являются хорошими С++ и обычно не хороши C. Языки расходятся, поскольку Stroustrup начал работать над "C с классами" и теперь менее похож на Когда-либо. Использование "C/С++" в качестве имени языка является prima facie доказательством того, что пользователь не знает, о чем он или она говорит. С++, правильно используемый, больше не похож на C, чем на Java или С#.

Ответ 7

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

Ответ 8

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

  • Это может быть статическая функция-член или переменная-член.
  • Это может быть статическая переменная или функция, объявленная в области пространства имен.
  • Это может быть статическая переменная, объявленная внутри функции.

Ответ 9

Массивы не являются указателями

Они разные. Поэтому &array не является указателем на указатель, а указателем на массив. По-моему, это самая непонятная концепция как на C, так и на С++. Вы должны посетить все те ответы SO, которые передают 2-мерные массивы как type**!

Ответ 10

Вот некоторые из них:

  • Использование шаблонов для реализации полиморфизма без vtables, à la ATL.
  • Логическое const -ness против фактического const -ness в памяти. Когда использовать ключевое слово mutable.

ПОДТВЕРЖДЕНИЕ: Спасибо за исправление моей ошибки, spoulson.

EDIT:

Вот еще:

  • Виртуальное наследование (а не виртуальные методы): На самом деле, я этого не понимаю! (я имею в виду, что я не знаю, как это реализовано)
  • Союзы, чьи члены являются объектами, соответствующие классы которых имеют нетривиальные конструкторы.

Ответ 11

Учитывая это:

int x = sizeof(char);

какое значение X?

Ответ, который вы часто слышите, зависит от уровня понимания спецификации.

  • Beginner - x является одним, потому что символы всегда имеют восемь бит.
  • Промежуточное - это зависит от реализации компилятора, символы могут быть в формате UTF16.
  • Expert - x является одним и всегда будет одним, так как char является наименьшей адресуемой единицей памяти, а sizeof определяет количество единиц памяти, необходимых для хранения экземпляра типа. Таким образом, в системе, где char - восемь бит, 32-битное значение будет иметь размер 4; но в системе, где char - 16 бит, 32-битное значение будет иметь размер 2.

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

Ответ 12

Вот важное понятие в С++, которое часто забывается:

С++ нельзя просто использовать как объект ориентированный язык, такой как Java или С#. Вдохните себя из STL и напишите общий код.

Ответ 13

классический среди новичков до С++ от c:

путать delete и delete[]

EDIT:

другой классический провал среди всех уровней опыта при использовании C API:

std::string helloString = "hello world";
printf("%s\n", helloString);

вместо:

printf("%s\n", helloString.c_str());

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

Ответ 14

Указатели.

Разыменование указателей. Через . или ->

Адрес использования & для указания указателя.

Функции, которые принимают параметры по ссылке, задавая & в сигнатуре.

Указатель на указатели на указатели *** или указатели по ссылке void someFunc(int *& arg)

Ответ 15

Есть несколько вещей, которые люди, кажется, постоянно путаются или не имеют представления о:

  • Указатели, особенно указатели на функции и несколько указателей (например, int (*) (void *), void ***)

  • Ключевое слово const и константная корректность (например, какая разница между константой const char *, char * const и const char * const, и что делает void class:: member() const; значит?)

  • Распределение памяти (например, каждый указатель new'ed должен быть удален, malloc/free не следует смешивать с новым/удалять, когда использовать delete [] вместо delete, почему функции C по-прежнему полезны (например, expand(), realloc()))

  • Область (т.е. вы можете использовать {} самостоятельно, чтобы создать новую область для имен переменных, а не только как часть if, для и т.д.)

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

  • Вызывающие соглашения (например, какая разница между cdecl и stdcall, как реализовать функцию pascal, почему это даже имеет значение?)

  • Наследование и множественное наследование и, в более общем смысле, вся парадигма OO.

  • Встроенный ассемблер, как он обычно реализуется, не является частью С++.

Ответ 16

С++ - это язык с несколькими парадигмами. Многие люди связывают С++ строго с ООП.

Ответ 17

  • Указатели на элементы и указатели на функции-члены.
  • Параметры шаблона непигового типа.
  • Множественное наследование, в частности виртуальные базовые классы и общие базовые объекты.
  • Порядок построения и уничтожения, состояние виртуальных функций в середине построения промежуточного базового класса.
  • Безопасность и переменные размеры. Нет, вы не можете предположить, что sizeof(void *) == sizeof(int) (или любой другой тип, если только портативный заголовок специально не гарантирует его) в переносном коде.
  • Арифметика указателя.

Ответ 18

Заголовки и файлы реализации

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

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

Ответ 19

Если функция принимает указатель на указатель, void* все равно сделает это

Я видел, что понятие указателя пустоты часто путается. Он считал, что если у вас есть указатель, вы используете void*, и если у вас есть указатель на указатель, вы используете void**. Но вы можете и должны в обоих случаях использовать void*. A void** не имеет специальных свойств, которые имеет a void*.

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

Ответ 20

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

Ответ 21

Выравнивание памяти.

Ответ 22

NULL всегда равен нулю.

Многие путают NULL с адресом и считают, что он не обязательно равен нулю, если платформа имеет другой адрес нулевой указатель.

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

Ответ 23

Хе-хе, это глупый ответ: самая непонятная вещь в программировании на C++ - это сообщения об ошибках из g++, когда классы шаблонов не скомпилируются!

Ответ 24

С++ не является C со строкой и вектором!

Ответ 25

С++ не является типичным объектно-ориентированным языком.

Не верьте мне? посмотрите STL, больше шаблонов, чем объектов.

Практически невозможно использовать методы Java/С# для написания объектно-ориентированного кода; он просто не работает.

  • В программировании на Java/С# имеется много new ing, множество объектов утилиты, которые реализуют некоторые единые связные функции.
  • В С++ любой объект new ed должен быть удален, но всегда существует проблема того, кто владеет объектом
  • В результате объекты, как правило, создаются в стеке
  • Но когда вы это делаете, вам приходится копировать их все время, если вы собираетесь передавать их другим функциям/объектам, таким образом тратя много работы, которая, как говорят, достигается с неуправляемой средой С++
  • Понимая это, вам нужно подумать о других способах организации вашего кода.
  • Вы можете в конечном итоге сделать что-то процедурным способом или использовать метапрограммирующие идиомы, такие как умные указатели.
  • На этом этапе вы поняли, что OO в С++ нельзя использовать так же, как и в Java/С#

Q.E.D.

Если вы настаиваете на выполнении указаний с указателями, у вас обычно будут большие (гигантские!) классы с четко определенными отношениями между объектами, чтобы избежать утечек памяти. И тогда, даже если вы это сделаете, вы уже слишком далеко от идиомы Java/С# oop.

На самом деле я составил термин "объектно-ориентированный", и могу сказать, что у меня не было С++. - Алан Кей (щелкните ссылку, это видео, цитата находится в 10:33)

Хотя с точки зрения пуриста (например, Алана Кей) даже Java и С# не соответствуют истинным oop

Ответ 26

Структуры C Структуры VS С++ часто неправильно понимаются.

Ответ 27

std::vector не создает элементы при использовании резерва

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

Ответ 28

Указатель - это итератор, но итератор не всегда является указателем

Это также неправильно понятая концепция. Указатель на объект - это итератор произвольного доступа: его можно увеличивать/уменьшать на произвольное количество элементов и читать и писать. Тем не менее, класс итератора, который выполняет перегрузку оператора, выполняет эти требования. Таким образом, он также является итератором, но, конечно, не является указателем.

Я помню, что один из моих прошлых учителей на С++ учил (ошибочно), что вы получаете указатель на элемент вектора, если вы делаете vec.begin(). Он фактически предполагал - не зная, - что вектор реализует свои итераторы с помощью указателей.

Ответ 29

  • Это анонимные пространства имен почти всегда то, что действительно нужно, когда люди создают статические переменные в С++
  • При создании файлов заголовков библиотеки, идиома pimpl (http://www.gotw.ca/gotw/024.htm) должна использоваться почти для всех частных функций и членов для помощи в управление зависимостями

Ответ 30

Я все еще не понимаю, почему в векторе нет pop_front и тот факт, что я не могу сортировать (list.begin(), list.end()).