Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Итог_Пособие C++.doc
Скачиваний:
8
Добавлен:
01.07.2025
Размер:
2 Мб
Скачать
☆

8.1 Выведение типов

Механизм автоматического выведения типов позволяет избавить программиста от необходимости самостоятельно указывать необходимый тип переменной при объявлении. В С++11 вместо типа можно указать ключевое слов auto, и компилятор самостоятельно выведет нужный тип.

// Пример 8.1 - автоматический вывод типов при инициализации переменных

int i = 1;

float f = 1.1;

auto i2 = 2;

auto f2 = 2.2;

std::cout << "i: " << i << ", " << "i2: " << i2 << std::endl;

std::cout << "f: " << f << ", " << "f2: " << f2 << std::endl;

Результат работы программы следующий:

i: 1, i2: 2

f: 1.1, f2: 2.2

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

// Пример 8.2 - автоматический вывод типов при вызове функции

const std::string& getString()

{

static std::string s = "Hello";

return s;

}

auto s = getString();

std::cout << s << std::endl;

Результат работы программы следующий:

Hello

При работе с контейнерами стандартной библиотеки ключевое слова auto может быть использовано для сокращения записи при указании типа итератора.

// Пример 8.3 - автоматический вывод типов при работе с итераторами

std::map<std::string, int> numbers = {

{"One", 1}, {"Two", 2}, {"Three", 3}

};

std::map<std::string, int>::const_iterator it = numbers.begin();

for(; it != numbers.end(); ++it)

std::cout << it->first << " , " << it->second << std::endl;

auto aIt = numbers.begin();

for(; aIt != numbers.end(); ++aIt)

std::cout << aIt->first << " , " << aIt->second << std::endl;

decltype(aIt) aIt2 = numbers.begin();

for(; aIt2 != numbers.end(); ++aIt2)

std::cout << aIt2->first << " , " << aIt2->second << std::endl;

Результат работы программы следующий:

One , 1

Three , 3

Two , 2

One , 1

Three , 3

Two , 2

One , 1

Three , 3

Two , 2

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

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

8.2 Списки инициализации

В стандарте С++11 вводится специальный класс для работы со списками инициализации, т.е. конструкциями вида {1,2,3,4,5} − std::initializer_list. Данный класс является шаблонным, экземпляры данного класса создаются компилятором статически. Список инициализации является константным и не может быть изменен во время работы программы.

Контейнерам стандартной библиотеки могут быть присвоены изначальные значения при помощи списка инициализации. Далее приведены два примера кода для контейнера std::vector и std::map.

// Пример 8.4 - начальное состояние контейнера std::vector, задаваемое

// с помощью списка инициализации.

std::cout << "Vector\n";

std::vector<int> vec = {1,2,3,4,5,6,7,8,9,10};

for(auto it = vec.begin(); it != vec.end(); ++it)

std::cout << *it << ' ';

std::cout << std::endl;

Результат работы программы следующий:

Vector

1 2 3 4 5 6 7 8 9 10

// Пример 8.5 - начальное состояние контейнера std::map, задаваемое

// с помощью списка инициализации.

std::cout << "Map\n";

std::map<std::string, std::string> m = {

{"Hello", "World"},{"Moscow","Russia"},{"London","GB"}};

for(std::map<std::string, std::string>::iterator it = m.begin(); it != m.end(); ++it)

std::cout << it->first << ", " << it->second << std::endl;

Результат работы программы следующий:

Map

Hello, World

London, GB

Moscow, Russia

Класс может содержать конструктор с параметром − списком инициализации, создание объекта такого класса будет схоже с созданием статического массива. Список инициализации может быть использован и для передачи параметров в функцию. В следующем фрагменте кода показаны обе эти возможности.

// Пример 8.6 - список инициализации в качестве параметра конструктора

class IListConstructed

{

int x, y, z;

public:

IListConstructed(std::initializer_list<int> il) {

x = *(il.begin() + 0);

y = *(il.begin() + 1);

z = *(il.begin() + 2);

}

void print() {

std::cout << "IListConstructed: " << x << y << z << std::endl;

}

void set(std::initializer_list<int> il) {

x = *(il.begin() + 0);

y = *(il.begin() + 1);

z = *(il.begin() + 2);

}

};

IListConstructed ic = {1,2,3};

ic.print();

ic.set({2,3,4});

ic.print();

Результат работы программы следующий:

IListConstructed: 123

IListConstructed: 234

В следующем фрагменте кода показан пример использования списка инициализации для передачи параметров в функцию. Для доступа к элементам списка инициализации используется итератор по аналогии с другими контейнерами стандартной библиотеки.

// Пример 8.7 - список инициализации в качестве параметра функции

int getMax(std::initializer_list<int> iList)

{

if(iList.size() == 0){

std::cout << "Empty initializer list" << std::endl;

return 0;

}

int value = *iList.begin();

for( std::initializer_list<int>::iterator it = iList.begin();

it != iList.end();

++it)

value = value > *it ? value : *it;

return value;

}

std::cout << getMax({3,2,1}) << std::endl;

std::cout << getMax({1,2,3}) << std::endl;

std::cout << getMax({}) << std::endl;

Результат работы программы следующий:

3

3

Empty initializer list

0