Си++ () — компилируемый строго типизированный язык программирования общего назначения. Поддерживает разные парадигмы программирования: процедурную, обобщённую, функциональную; наибольшее внимание уделено поддержке объектно-ориентированного программирования.
В 1990-х годах Си++ стал одним из наиболее широко применяемых языков программирования общего назначения.
При создании Си++ стремились сохранить совместимость с языком Си. Большинство программ на Си будут исправно работать и с компилятором Си++.
Нововведениями Си++ в сравнении с Си являются: поддержка объектно-ориентированного программирования через классы, поддержка обобщённого программирования через шаблоны, дополнения к стандартной библиотеке, дополнительные типы данных, исключения, пространства имён, встраиваемые функции, перегрузка операторов, перегрузка имён функций, ссылки и операторы управления свободно распределяемой памятью.
Язык возник в начале 1980-х годов, когда сотрудник Лабораторий Bell Бьярне Строуструп придумал ряд усовершенствований к языку Си под собственные нужды. До начала официальной стандартизации язык развивался в основном силами Строуструпа в ответ на запросы программистского сообщества. В 1998 году был ратифицирован международный стандарт языка Си++: ISO/IEC 14882:1998 «Standard for the C++ Programming Language»; после принятия технических исправлений к стандарту в 2003 году нынешняя версия этого стандарта — ISO/IEC 14882:2003.
Название «Си++» происходит от Си, в котором унарный оператор ++ обозначает приращение.
В «Дизайне и Развитии C++» (ISBN 0-201-54330-3) Бьярн Страуструп описывает некоторые правила, которые он использовал при проектировании Си++. Знание этих правил может помочь понять, почему Си++ такой, каким он стал. Вот некоторые из этих правил. Подробности можно найти в Дизайне и Развитии C++.
Страуструп начал работать над «Си с классами» в 1979 году. Идея создания нового языка берёт начало от опыта программирования Страуструпа для диссертации. Он обнаружил, что язык моделирования Симула (Simula) имеет такие возможности, которые были бы очень полезны для разработки большого программного обеспечения, но работает слишком медленно. В то же время язык BCPL достаточно быстр, но слишком близок к языкам низкого уровня и не подходит для разработки большого программного обеспечения. Страуструп начал работать в лабораториях Bell над задачами теории очередей (в приложении к моделированию телефонных вызовов). Попытки применения существующих в то время языков моделирования оказались неэффективными. Вспоминая опыт своей диссертации, Страуструп решил дополнить язык Си (преемник BCPL) возможностями, имеющимися в языке Симула. Язык Си, будучи базовым языком системы UNIX, на которой работали компьютеры Bell является быстрым, многофункциональным и переносимым. Страуструп добавил к нему возможность работы с классами и обьектами. В результате, практические задачи моделирования оказались доступными для решения как с точки зрения времени разработки (благодаря использованию Симула-подобных классов) так и с точки зрения времени вычислений (благодаря быстродействию Си). В начале в Си были добавлены классы (с инкапсуляцией), производные классы, строгая проверка типов, inline-функции и аргументы по умолчанию.
Разрабатывая Си с классами (позднее Си++), Страуструп также написал программу Cfront, компилятор, перерабатывающий исходный код Си с классами в исходный код простого Си. Новый язык, неожиданно для автора, приобрел большую популярность среди коллег и вскоре Страустроп уже не мог лично поддерживать его, отвечая на тысячи вопросов.
В 1983 произошло переименование языка из Си с классами в Си++ по соображениям маркетинга. Кроме того в него были добавлены новые возможности, такие как виртуальные функции, перегрузка функций и операторов, ссылки, константы, пользовательский контроль над управлением свободной памятью, улучшенная проверка типов и новый стиль комментариев (//). Его первый коммерческий выпуск состоялся в октябре 1985. В 1985 вышло первое издание «Языка программирования Си++», обеспечивающее первое описание этого языка, что было чрезвычайно важно из-за отсутствия официального стандарта. В 1989 состоялся выход Си++ версии 2.0. Его новые возможности включали множественное наследование, абстрактные классы, статические функции-члены, функции-константы и защищённые члены. В 1990 вышло «Комментированное справочное руководство по C++», положенное впоследствии в основу стандарта. Последние обновления включали шаблоны, исключения, пространства имён, новые способы приведения типов и булевский тип.
Стандартная библиотека Си++ также развивалась вместе с ним. Первым добавлением к стандартной библиотеке Си++ стали потоки ввода/вывода, обеспечивающие средства для замены традиционных функций Си printf и scanf. Позднее самым значительным развитием стандартной библиотеки стало включение в неё Стандартной Библиотеки Шаблонов.
После многих лет работы совместный комитет ANSI-ISO стандартизировал Си++ в 1998 (ISO/IEC 14882:1998). В течение нескольких лет после официального выхода стандарта комитет обрабатывал сообщения об ошибках и в итоге выпустил исправленную версию стандарта Си++ в 2003 году.
Никто не обладает правами на язык Си++, он является свободным. Однако, к сожалению, сам документ стандарта языка недоступен бесплатно.
Подводя, с удовлетворением, итоги своей деятельности создатель языка недавно заметил: "В начале своей деятельности я мечтал, что настанет время, когда компьютером будет также легко пользоваться как и телефоном. Мне удалось дожить до осуществления моей мечты. Теперь, прежде чем первый раз позвонить по телефону новой конструкции я должем изучить 500-страничную инструкцию"
В 1998 году язык Си++ был стандартизован Международной организацией стандартизации под номером 14882:1998 — Язык Программирования Си++. В настоящее время рабочая группа МОС работает над новой версией стандарта под кодовым названием C++0X.
Стандарт Си++ на 1998 год состоит из двух основных частей: ядра языка и стандартной библиотеки.
Стандартная библиотека Си++ вобрала в себя разрабатывавшуюся одновременно со стандартом библиотеку шаблонов STL. Сейчас название STL официально не употребляется, однако в кругах программистов на Си++ это название используется для обозначения части стандартной библиотеки, содержащей определения шаблонов контейнеров, итераторов, алгоритмов и функторов.
Стандарт Си++ содержит нормативную ссылку на стандарт Си от 1990 года и не определяет самостоятельно те функции стандартной библиотеки, которые заимствуются из стандартной библиотеки Си.
Кроме того, существует огромное количество библиотек Си++, не входящих в стандарт. В программах на Си++ можно использовать многие библиотеки Си.
Стандартизация определила язык программирования Си++, однако за этим названием могут скрываться также неполные, ограниченные достандартные варианты языка. В первое время язык развивался вне формальных рамок, спонтанно, по мере ставившихся перед ним задач. Развитию языка сопутствовало развитие кросс-компилятора Cfront. Новшества в языке отражались в изменении номера версии кросс-компилятора. Эти номера версий кросс-компилятора распространялись и на сам язык, но применительно к настоящему времени речь о версиях языка Си++ не ведут.
Язык Си++ во многом является надмножеством Си. Новые возможности Си++ включают объявления в виде выражений, преобразования типов в виде функций, операторы new и delete, тип bool, ссылки, расширенное понятие константности, подставляемые функции, аргументы по умолчанию, переопределения, пространства имён, классы (включая и все связанные с классами возможности, такие как наследование, функции-члены, виртуальные функции, абстрактные классы и конструкторы, переопределения операторов, шаблоны, оператор ::, обработку исключений, динамическую идентификацию и многое другое. Язык Си++ также во многих случаях строже относится к проверке типов, чем Си.
В Си++ появились комментарии в виде двойной косой черты («//»), которые были в предшественнике Си — языке BCPL.
Некоторые особенности Си++ позднее были перенесены в Си, например ключевые слова const и inline, объявления в циклах for и комментарии в стиле Си++ («//»). В более поздних реализациях Си также были представлены возможности, которых нет в Си++, например макросы vararg и улучшенная работа с массивами-параметрами.
В этом разделе описываются возможности, непосредственно не связанные с объектно-ориентированным программированием (ООП). Многие из них, однако, особенно важны в сочетании с ООП.
Стандартная библиотека Си++ включает стандартную библиотеку Си с небольшими изменениями, которые делают её более подходящей для языка Си++. Другая большая часть библиотеки Си++ основана на Стандартной Библиотеке Шаблонов (STL). Она предоставляет такие важные инструменты, как контейнеры (например, векторы и списки) и итераторы (обобщённые указатели), предоставляющие доступ к этим контейнерам как к массивам. Кроме того, STL позволяет сходным образом работать и с другими типами контейнеров, например, ассоциативными списками, стеками, очередями.
Используя шаблоны, можно писать обобщённые алгоритмы, способные работать с любыми контейнерами или последовательностями, определяемыми итераторами.
Так же, как и в Си, возможности библиотек активизируются использованием директивы #include для включения стандартных файлов. Всего в стандарте Си++ определено 50 таких файлов.
STL до включения в стандарт Си++ была сторонней разработкой, в начале — фирмы HP, а затем SGI. Стандарт языка не называет её «STL», так как эта библиотека стала неотъемлемой частью языка, однако многие люди до сих пор используют это название, чтобы отличать её от остальной части стандартной библиотеки (потоки ввода/вывода (Iostream), подраздел Си и др.).
Проект под названием STLPort, основанный на SGI STL, осуществляет постоянное обновление STL, IОstream и строковых классов. Некоторые другие проекты также занимаются разработкой частных применений стандартной библиотеки для различных конструкторских задач. Каждый производитель компиляторов Си++ обязательно поставляет какую-либо реализацию этой библиотеки, так как она является очень важной частью стандарта и широко используется.
Си++ добавляет к Си объектно-ориентированные возможности. Он вводит классы, которые обеспечивают три самых важных свойства ООП: инкапсуляцию, наследование и полиморфизм.
В языке C основным способом организации данных были структуры. Структура состоит из набора полей, которые никак не защищены. Если элементы структуры имеют переменную длину, их представляют в виде указателей. Выделение и освобождение памяти под эти указатели делаются вручную. Так, например, одномерный массив переменной длины в языке C с проверкой границ может представлятся таким образом:
struct Array { double* val; int len; };
void FreeArray(const struct Array*); void AllocArray(const struct Array*, int len); double Elem(const struct Array*, int i); void ChangeElem(const struct Array*, int i, double x);
Такая реализация опасна и неэффективна по многим причинам:
Язык Си++ , используя ООП, устраняет все эти проблемы.
Основным способом организации информации в Си++ являются классы. В отличие от типа структура (struct) языка Си, состоящей только из полей, класс (class) Си++ состоит из полей и функций-членов (member functions). Поля бывают публичными (public), защищёнными (protected) и собственными (приватными, private). В Си++ тип структура аналогичен типу класс, отличие в том, что по умолчанию поля и функции-члены у структуры публичные, а у класса - собственные.
С публичными полями можно делать снаружи класса всё, что угодно. К защищённым и собственным полям нельзя обращаться извне класса, чтобы не нарушить целостность данных класса. Попытка такого обращения вызовет ошибку компиляции. К таким полям могут обращаться только функции-члены класса (а также так называемые функции-друзья и функции-члены классов-друзей; о понятии друзей в C++ см. ниже.) Вне тела функций-членов (а также друзей) защищённые и собственные поля недоступны даже для чтения. Такая защита полей называется инкапсуляцией.
Используя инкапсуляцию, автор класса может защитить свои данные от некорректного использования. Кроме того, она задумывалась для облегчения совместной разработки классов. Имелось ввиду, что при изменении способа хранения данных, если они объявлены как защищенные или собственные, не требуется соответствующих изменений в классах, которые используют измененный класс. Например, если в старой версии класса данные хранились в виде линейного списка, а в новой версии - в виде дерева, те классы, которые были написаны до изменения формата хранения данных, переписывать не потребуется, если данные были приватными или защищенными (в последнем случае - если использующие классы не были классами-наследниками), так как ни один из них этих классов не мог бы напрямую обращаться к данным, а только через стандартные функции, которые в новой версии должны уже корректно работать с новым форматом данных. Даже оператор доступа operator * может быть определён как такая стандартная функция.
Функции-члены, как и поля, могут быть публичными, защищёнными и собственными. Публичные функции может вызывать кто угодно, а защищённые и собственные - только функции-члены и друзья.
Используя инкапсуляцию, структуру Array из предыдущего раздела можно переписать следующим образом: class Array { public: void Alloc(int _len); void Free(); inline double Elem(int i); inline void ChangeElem(int i, double x); protected: int len; double* val; };
void Array::Alloc(int new_len)
{if (len>0) Free(); val=new double*;}
void Array::Free() {delete * val; len=0;}
inline void Array::Elem(int i)
{assert(i>=0 && i
И далее
Array a; a.Alloc(10); a.ChangeElem(3, 2.78); double b = a.Elem(3); a.Free();
Здесь массив a имеет 4 публичных функции-члена и 2 защищённых поля. Описатель inline означает, что вместо вызова функции ее код подставляется в точку вызова, что решает проблему неэффективности.
В теле класса можно указать только заголовок функции, а можно описать всю функцию. Во втором случае она считается встроенной (inline), например:
class Array { public: void Alloc(int _len) {if (len==0) Free(); len=_len; val=new double*;}
и так далее.
Однако в приведённом примере не решена важная проблема: функции Alloc и Free по-прежнему надо вызывать вручную. Другая проблема данного примера — опасность оператора присваивания.
Для решения этих проблем в язык были введены конструкторы и деструкторы. Конструктор вызывается каждый раз, когда создаётся объект данного типа; деструктор - при уничтожении. При преобразованиях типов, присваивании, передаче параметра тоже вызываются конструкторы и при необходимости деструкторы.
С конструкторами и деструктором класс выглядит так:
class Array { public: Array() : len(0), val(NULL); Array(int _len) : len(_len) {val = new double*;} Array(const Array& a); ~Array() : Free(); inline double Elem(int i); inline void ChangeElem(int i, double x); protected: void Alloc(int _len); void Free(); int len; double* val; };
Array::Array(const Array& a) : len(a.len)
{
val = new double*;
for (int i=0; i
Здесь Array::Array - конструктор, а Array::~Array - деструктор. Конструктор копирования (copy constructor) Array::Array(const Array&) вызывается при присваивании. Теперь объект класса Array нельзя испортить: как бы мы его ни создавали, что бы мы ни делали, его значение будет хорошим, потому что конструктор вызывается автоматически. Все опасные операции с указателями спрятаны в защищённые функции.
Array a(5); // вызывается Array::Array(int) Array b; // вызывается Array::Array() Array c(a); // вызывается Array::Array(const Array&) Array d=a; // то же самое b=c; // происходит вызов оператора = // если он не определен (как в данном случае), то // вызывается Array::Array(const Array&)
Оператор new тоже вызывает конструкторы, а delete - деструкторы.
По умолчанию, каждый класс имеет конструктор без параметров и деструктор. Конструктор без параметров по умолчанию вызывает конструкторы всех элементов, а деструктор - их деструкторы. Другие конструкторы по умолчанию не определены.
Класс может иметь сколько угодно конструкторов (с разными наборами параметров), но только один деструктор (без параметров).
Функции-члены могут быть и операциями:
class Array { ... inline double &operator* (int n);
И далее
Array a(10); ... double b = a*;
Функции-члены (и только они) могут иметь описатель const class Array { ... inline double operator* (int n) const; Такие функции не имеют права изменять поля класса. Если они пытаются это сделать, компилятор должен выдать сообщение об ошибке.
Для создания классов с добавленной функциональностью вводят наследование. Класс-наследник имеет поля и функции-члены базового класса, но не имеет права обращаться к собственным (private) полям и функциям базового класса. В этом и заключается разница между собственными и защищёнными членами.
Класс-наследник может добавлять свои поля и функции или переопределять функции базового класса.
По умолчанию, конструктор наследника без параметров вызывает конструктор базового класса, а затем конструкторы добавленных элементов. Деструктор работает в обратном порядке. Другие конструкторы приходится определять каждый раз заново. К счастью, это можно сделать вызовом конструктора базового класса.
class ArrayWithAdd : public Array { ArrayWithAdd(int n) : Array(n) {} ArrayWithAdd() : Array() {} ArrayWithAdd(const Array& a) : Array(a) {} void Add(const Array& a); };
Наследник - это больше чем базовый класс, поэтому он может использоваться везде, где используется базовый класс, но не наоборот.
Наследование бывает публичным, защищённым и собственным. При публичном наследовании, публичные и защищённые члены базового класса сохраняют свой статус, а к собственным не могут обращаться даже функции-члены наследника. Защищённое наследование отличается тем, что при нём публичные члены базового класса являются защищёнными членами наследника. При собственном наследовании, ни к каким членам базового класса даже функции-члены наследника не имают права обращаться. Как правило, публичное наследование встречается значительно чаще других.
Класс может быть наследником нескольких классов. Это называется множественным наследованием. Такой класс обладает полями и функциями-членами всех его предков. Например, класс FlyingCat (ЛетающийКот) может быть наследником классов Cat (Кот) i FlyingAnimal (ЛетающееЖивотное) class Cat { ... void Purr(); ... }; class FlyingAnimal { ... void Fly(); ... }; class FlyingCat : public Cat, public FlyingAnimal { ... PurrAndFly() {Purr(); Fly();} ... };
Полиморфизмом называется переопределение наследником функций-членов базового класса, например class Figure { ... void Draw() const; ... };
class Square : public Figure { ... void Draw() const; ... };
class Circle : public Figure { ... void Draw() const; ... };
В этом примере, какая из функций будет вызвана - Circle::Draw(), Square::Draw() или Figure::Draw(), определяется во время компиляции. К примеру, если написать Figure* x = new Circle(0,0,5); x->Draw(); то будет вызвана Figure::Draw(), поскольку x - объект класса Figure. Такой полиморфизм называется статическим.
Но в C++ есть и динамический полиморфизм, когда вызываемая функция определяется во время выполнения. Для этого функции-члены должны быть виртуальными.
class Figure { ... virtual void Draw() const; ... };
class Square : public Figure { ... virtual void Draw() const; ... };
class Circle : public Figure { ... virtual void Draw() const; ... };
Figure* figures*; figures* = new Square(1,2,10); figures* = new Circle(3,5,8); ... for (int i=0; i<10; i++) figures* -> Draw();
В этом случае для каждого элемента будет вызвана Square::Draw() или Circle::Draw() в зависимости от вида фигуры.
Чисто виртуальной функцией называется функция-член, которая не определена в базовом классе, а только в наследниках: class Figure { ... virtual void Draw() const = 0; Вот это = 0 и значит, что функция чисто виртуальная.
Чисто виртуальным классом называется такой, у которого есть хотя бы одна чисто виртуальная функция-член. Объекты таких классов создавать запрещено.
Функции-друзья — это функции, не являющиеся функциями-членами и тем не менее имеющие доступ к защищённым и собственным полям и функциям-членам класса. Они должны быть описаны в теле класса как friend. Например: class Matrix { ... friend Matrix Multiply(Matrix m1, Matrix m2); ... }; Matrix Multiply(Matrix m1, Matrix m2) { ... }
Здесь функция Multiply может обращаться к любым полям и функциям-членам класса Matrix.
Существуют также классы-друзья. Если класс A - друг класса B, то все его функции-члены могут обращаться к любым полям и функциям членам класса B. Например: class Matrix { ... friend class Vector; ... };
Однако в С++ не действует правило «друг моего друга — мой друг».
Си++ продолжает развиваться, чтобы отвечать современным требованиям. Одна из групп, занимающихся языком Си++ в его современном виде и направляющих комитету по стандартизации Си++ советы по его улучшению — это Boost. Например, одно из направлений деятельности этой группы — совершенствование возможностей языка путём добавления в него особенностей метапрограммирования.
Стандарт Си++ не описывает способы именования объектов, некоторые детали обработки исключений и другие возможности, связанные с деталями реализации, что делает несовместимым объектный код, созданный различными компиляторами. Однако для этого третьими лицами создано множество стандартов для конкретных архитектур и операционных систем.
Тем не менее (по состоянию на время написания этой статьи) среди компиляторов Си++ всё ещё продолжается битва за полную реализацию стандарта Си++, особенно в области шаблонов — части языка, совсем недавно полностью разработанной комитетом стандартизации.
Одной из точек преткновения в этом вопросе является ключевое слово export, используемое также и для разделения объявления и определения шаблонов.
Первым компилятором, поддерживающим export в шаблонах, стал Comeau C++ в начале 2003 года (спустя пять лет после выхода стандарта). В 2004 году бета-версия компилятора Borland C++ Builder X также начала его поддержку.
Оба этих компилятора основаны на внешнем интерфейсе EDG. Другие компиляторы, такие как Microsoft Visual C++ или GCC, вообще этого не поддерживают. Эрб Саттер (Herb Sutter), секретарь комитета по стандартизации Си++, рекомендовал убрать export из будущих версий стандарта по причине серьёзных сложностей в полноценной реализации, однако впоследствии окончательным решением было решено его оставить.
Из списка других проблем, связанных с шаблонами, можно привести вопросы конструкций частичной специализации шаблонов, которые плохо поддерживались в течение многих лет после выхода стандарта Си++.
Это имя было изобретено Риком Маскитти (Rick Mascitti) и было впервые использовано в декабре 1983 года. Ранее, на этапе разработки, новый язык называли «Си с классами». Имя, получившееся в итоге, происходит от оператора Си «++» (увеличение значения переменной на единицу) и распространённому способу присвоения новых имён компьютерным программам, заключающимся в добавлении к имени символа «+» для обозначения улучшений (например «Википедия+»). Согласно Страуструпу: «это название указывает на эволюционную природу изменений Cи». Ранее выражение «С+» обозначало несвязанную программу.
Некоторые программисты на Си могут заметить, что если выполняются выражения x=3; y=x++; то в результате получится x=4 и y=3, потому, что x увеличивается только после присвоения его y. Однако, если второе выражение будет y=++x; то получится x=4 и y=4. Исходя из этого, можно сделать вывод, что более логично было бы назвать язык не Си++, а ++Си. Однако оба выражения c++ и ++c увеличивают c, а кроме того выражение c++ более распространено. Педанты также могут заметить, что введение языка Си++ не изменяет самого Си, поэтому самым точным именем было бы «С+1».
Несмотря на то, что большая часть кода Си будет справедлива и для Си++, Си++ не является надмножеством Си и не включает его в себя. Существует и такой верный для Си код, который неверен для Си++. Это отличает его от Объектного Си (Objective-C), ещё одного усовершенствования Си для ООП, как раз являющегося надмножеством Си.
Более того, код, верный для обоих Си и Си++, может давать разные результаты в зависимости от того, где он скомпилирован.
Например, следующая программа печатает «С», если компилируется компилятором Си, и «Си++» — если компилятором Си++. Так происходит из-за того, что символьные константы в Си (например 'a') представлены целым типом int, а в Си++ — типом char.
#include
int main() { printf("%s\n", (sizeof('a') == sizeof(char)) ? "C++" : "C"); return 0; } Конечно существуют и другие различия. Например Си++ не разрешает вызывать функцию main() внутри программы, в то время как в Си это действие правомерно. Кроме того Си++ более строг в некоторых вопросах, например он не допускает неявное приведение типов между несвязанными типами указателей и не разрешает использовать функции, которые не были ещё объявлены.
Смотрите статью язык Си.
Это пример программы, которая не делает ничего. Она начинает выполняться и немедленно завершается. Она состоит из единственной вещи: функции main(), которая обозначает точку начала выполнения программы на Си++. int main() { return 0; } Стандарт Си++ требует, чтобы функция main() возвращала тип int. Программа, которая имеет другой тип возвращаемого значения функции main(), не соответствует стандарту Си++.
Стандарт не говорит о том, что на самом деле означает возвращаемое значение функции main(). Традиционно оно интерпретируется как код возврата программы. Стандарт гарантирует, что возвращение 0 из функции main() показывает, что программа была завершена успешно.
Завершение программы на Си++ с ошибкой традиционно обозначается путём возврата ненулевого значения.
Эта программа также ничего не делает, но более лаконична. int main(){} В Си++, если выполнение программы доходит до конца функции main(), то это эквивалентно return 0;. Это неверно для любой другой функции кроме main(). Строго говоря, эта программа не является программой на Си++, желающие могут обратиться к H.Sutter "Exceptional C++".
Это пример программы Hello World, которая выводит это знаменитое сообщение, используя стандартную библиотеку, и завершается.
#include
Современный Си++ позволяет решать простым способом и более сложные задачи. Этот пример демонстрирует кроме всего прочего использование контейнеров стандартной библиотеки шаблонов (STL).
#include
using namespace std; // используем пространство имён "std"
void display_item_count(pair< string const, vector
int main() {
// объявляем карту со строковыми ключами и данными в виде векторов строк
map< string, vector
// Добавим в эту карту пару человек и дадим им несколько предметов items*.push_back("scarf"); items*.push_back("tickets"); items*.push_back("puppy");
// Переберём все объекты в контейнере
for_each(items.begin(), items.end(), display_item_count);
}
В этом примере для простоты используется директива использования пространства имён, в настоящей же программе обычно рекомендуется использовать объявления, которые аккуратнее директив:
#include
int main() { using std::vector;
vector
Языки Java обладает следующими особенностями, которых нет в языке C++
Эти отличия приводят к ожесточённым спорам между сторонниками двух языков о том, какой язык лучше. Сторонники Java считают эти особенности преимуществами; сторонники C++ считают, что во многих случаях эти особенности являются недостатками, в частности
Далеко не все программисты являются сторонниками одного из языков. По мнению большинства программистов, Java и C++ не являются конкурентами, потому что обладают различными областями применимости. Другие считают, что выбор языка для многих задач является вопросом личного вкуса.
C++ | C++ | سي++ | Си плюс плюс | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | سیپلاسپلاس | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | C++ | ภาษาซีพลัสพลัส | C++ | C++ | C++ | C++