Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих.pdf
Скачиваний:
199
Добавлен:
01.05.2014
Размер:
3.97 Mб
Скачать

int ia[ 7 ] = { 0, 1, 1, 2, 3, 5, 8 };

(a)vector< vector< int > > ivec;

(b)vector< int > ivec = { 0, 1, 1, 2, 3, 5,

8};

(c)vector< int > ivec( ia, ia+7 );

(d)vector< string > svec = ivec;

Имеются ли ошибки в следующих определениях?

(e) vector< string > svec( 10, string( "null" ));

Упражнение 3.25

bool is_equa1( const int*ia, int ia_size,

Реализуйте следующую функцию:

const vector<int> &ivec );

Функция is_equal() сравнивает поэлементно два контейнера. В случае разного размера контейнеров “хвост” более длинного в расчет не принимается. Понятно, что, если все сравниваемые элементы равны, функция возвращает true, если отличается хотя бы один – false. Используйте итератор для перебора элементов. Напишите функцию main(), обращающуюся к is_equal().

3.11. Класс complex

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

#include <comp1ex>

Комплексное число состоит из двух частей – вещественной и мнимой. Мнимая часть представляет собой квадратный корень из отрицательного числа. Комплексное число принято записывать в виде

2 + 3i

где 2 – действительная часть, а 3i – мнимая. Вот примеры определений объектов типа complex:

//чисто мнимое число: 0 + 7-i comp1ex< double > purei( 0, 7 );

//мнимая часть равна 0: 3 + Oi comp1ex< float > rea1_num( 3 );

//и вещественная, и мнимая часть равны 0: 0 + 0- i

comp1ex< long double > zero;

// инициализация одного комплексного числа другим comp1ex< double > purei2( purei );

Поскольку complex, как и vector, является шаблоном, мы можем конкретизировать его типами float, double и long double, как в приведенных примерах. Можно также

complex< double > conjugate[ 2 ] =

{

complex< double >( 2, 3 ), complex< double >( 2, -3 )

определить массив элементов типа complex:

};

complex< double > *ptr = &conjugate[0];

Вот как определяются указатель и ссылка на комплексное число: complex< double > &ref = *ptr;

Комплексные числа можно складывать, вычитать, умножать, делить, сравнивать, получать значения вещественной и мнимой части. (Более подробно мы будем говорить о классе complex в разделе 4.6.)

3.12. Директива typedef

Директива typedef позволяет задать синоним для встроенного либо пользовательского

typedef double

wages;

typedef vector<int>

vec_int;

typedef vec_int

test_scores;

typedef bool

 

in_attendance;

типа данных. Например:

typedef int *Pint;

Имена, определенные с помощью директивы typedef, можно использовать точно так же, как спецификаторы типов:

//double hourly, weekly; wages hourly, weekly;

//vector<int> vecl( 10 ); vec_int vecl( 10 );

//vector<int> test0( c1ass_size ); const int c1ass_size = 34;

test_scores test0( c1ass_size );

// vector< bool > attendance; vector< in_attendance >

attendance( c1ass_size );

// int *table[ 10 ]; Pint table [ 10 ];

Эта директива начинается с ключевого слова typedef, за которым идет спецификатор типа, и заканчивается идентификатором, который становится синонимом для указанного типа.

Для чего используются имена, определенные с помощью директивы typedef? Применяя мнемонические имена для типов данных, можно сделать программу более легкой для восприятия. Кроме того, принято употреблять такие имена для сложных составных типов, в противном случае воспринимаемых с трудом (см. пример в разделе 3.14), для объявления указателей на функции и функции-члены класса (см. раздел 13.6).

Ниже приводится пример вопроса, на который почти все дают неверный ответ. Ошибка вызвана непониманием директивы typedef как простой текстовой макроподстановки. Дано определение:

typedef char *cstring;

Каков тип переменной cstr в следующем объявлении:

extern const cstring cstr;

Ответ, который кажется очевидным:

const char *cstr

Однако это неверно. Спецификатор const относится к cstr, поэтому правильный ответ – константный указатель на char:

char *const cstr;

3.13. Спецификатор volatile

Объект объявляется как volatile (неустойчивый, асинхронно изменяемый), если его значение может быть изменено незаметно для компилятора, например переменная, обновляемая значением системных часов. Этот спецификатор сообщает компилятору, что не нужно производить оптимизацию кода для работы с данным объектом.

Спецификатор volatile используется подобно спецификатору const:

volatile int disp1ay_register;

volatile Task *curr_task; volatile int ixa[ max_size ];

volatile Screen bitmap_buf;

display_register – неустойчивый объект типа int. curr_task – указатель на неустойчивый объект класса Task. ixa – неустойчивый массив целых, причем каждый элемент такого массива считается неустойчивым. bitmap_buf – неустойчивый объект класса Screen, каждый его член данных также считается неустойчивым.

Единственная цель использования спецификатора volatile – сообщить компилятору, что тот не может определить, кто и как может изменить значение данного объекта. Поэтому компилятор не должен выполнять оптимизацию кода, использующего данный объект.

3.14. Класс pair

Класс pair (пара) стандартной библиотеки С++ позволяет нам определить одним объектом пару значений, если между ними есть какая-либо семантическая связь. Эти значения могут быть одинакового или разного типа. Для использования данного класса необходимо включить заголовочный файл:

#inc1ude <uti1ity>

Например, инструкция

pair< string, string > author( "James", "Joyce" );

создает объект author типа pair, состоящий из двух строковых значений.

string firstBook;

if ( Joyce.first == "James"

&&

Joyce.second == "Joyce" )

Отдельные части пары могут быть получены с помощью членов first и second: firstBook = "Stephen Hero";

Если нужно определить несколько однотипных объектов этого класса, удобно

typedef pair< string, string > Authors;

Authors proust( "marcel", "proust" );

Authors joyce( "James", "Joyce" );

использовать директиву typedef:

Authors musil( "robert", "musi1" );