Второй оператор выводит endl
— специальное значение, называемое манипулятором (manipulator). При его записи в поток вывода происходит переход на новую строку и сброс буфера (buffer), связанного с данным устройством. Сброс буфера гарантирует, что весь вывод, который программа сформировала на данный момент, будет немедленно записан в поток вывода, а не будет ожидать записи, находясь в памяти.
Во время отладки программисты зачастую добавляют операторы вывода промежуточных значений. Для таких операторов всегда следует применять сброс потока. Если этого не сделать, оставшиеся в буфере вывода данные в случае сбоя программы могут ввести в заблуждение разработчика, неправильно засвидетельствовав место возникновения проблемы.
Внимательный читатель, вероятно, обратил внимание на то, что в этой программе использована форма записи std::cout
и std::endl
, а не просто cout
и endl
. Префикс std::
означает, что имена cout
и endl
определены в пространстве имен (namespace) по имени std
. Пространства имен позволяют избежать вероятных конфликтов, причиной которых является совпадение имен, определенных в разных библиотеках. Все имена, определенные в стандартной библиотеке, находятся в пространстве имен std
.
Побочным эффектом применения пространств имен библиотек является то, что названия используемых пространств приходится указывать явно, например std
. В записи std::cout
применяется оператор области видимости ::
(scope operator), позволяющий указать, что здесь используется имя cout
, которое определено в пространстве имен std
. Как будет продемонстрировано в разделе 3.1, существует способ, позволяющий программисту избежать частого использования подробного синтаксиса.
Отобразив приглашение к вводу, необходимо организовать чтение введенных пользователем данных. Сначала следует определить две переменные (variable), в данном случае v1
и v2
, которые и будут содержать введенные данные:
int v1 = 0, v2 = 0;
Эти переменные определены как относящиеся к типу int
, который является встроенным типом данных для целочисленных значений. Мы также инициализируем (initialize) их значением 0. При инициализации переменной ей присваивается указанное значение в момент создания.
Следующий оператор читает введенные пользователем данные:
std::cin >> v1 >> v2;
Оператор ввода (input operator) (т.е. оператор >>
) ведет себя аналогично оператору вывода. Его левым операндом является объект типа istream
, а правым операндом — объект, заполняемый данными. Он читает значение из потока, представляемого объектом типа istream
, и сохраняет его в объекте, заданном правым операндом. Подобно оператору вывода, оператор ввода возвращает в качестве результата свой левый операнд. Другими словами, эта операция эквивалентна следующей:
(std::cin >> v1) >> v2;
Поскольку оператор возвращает свой левый операнд, мы можем объединить в одном операторе последовательность из нескольких запросов на ввод данных. Наше выражение ввода читает из объекта std::cin
два значения, сохраняя первое в переменной v1
, а второе в переменной v2
. Другими словами, рассматриваемое выражение ввода выполняется как два следующих:
std::cin >> v1;
std::cin >> v2;
Теперь осталось лишь вывести результат сложения на экран.
std::cout << "The sum of " << v1 << " and " << v2
<< " is " << v1 + v2 << std::endl;
Хоть этот оператор и значительно длиннее оператора, отобразившего приглашение к вводу, принципиально он ничем не отличается. Он передает значения каждого из своих операндов в поток стандартного устройства вывода. Здесь интересен тот факт, что не все операнды имеют одинаковый тип значений. Некоторые из них являются строковыми литералами, например "The sum of "
, другие значения относятся к типу int
, например v1
и v2
, а третьи представляют собой результат вычисления арифметического выражения v1 + v2
. В библиотеке определены версии операторов ввода и вывода для всех этих встроенных типов данных.