Выведите свои навыки C ++ на новый уровень, используя «современный» C ++

Вы знаете синтаксис и кодирование на языке C ++. Но знаете ли вы, что делает вас современным программистом на C ++? Использует ли ваш код функции, представленные в C ++ 11, 14 или 17? Используете ли вы в своем приложении классы стандартной библиотеки? Знаете ли вы о лямбда-функциях C ++, интеллектуальных указателях и выразительных циклах for?

Если ваш ответ отрицательный, вот несколько советов, которые помогут вам улучшить свои навыки программирования на C ++ и сделать вас современным программистом на C ++.

1. Стандартные библиотечные контейнеры

Vector, Array и List - это базовые библиотечные контейнеры, используемые в C ++.

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

Если размер контейнера фиксированный напр. Месяцев в году (12), используйте вместо этого std: array. В отличие от Vector, Array выделяет память в стеке и обеспечивает более быстрый доступ к элементам.

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

В дополнение к этому, C ++ также предоставляет другие стандартные библиотечные контейнеры, такие как stack, queue, dequeue, priority_queue, карта, unordered_map.

Стек полезен для операций push, pop, top над элементами в контейнере.

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

Dequeue аналогично очереди, но выполняет операции с элементами в начале и в конце очереди.

Priority Queue аналогично очереди, но вставляет элемент в контейнер на основе приоритета, связанного с ними, например. вставлять студентов в зависимости от ранга

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

Неупорядоченная карта - это пары ключей и значений без сортировки.

Если вы новичок в C ++, начните с использования vector. Если вы чувствуете, что вам нужен стек или карта, продолжайте и начните использовать эти контейнеры. Также напишите свой код таким образом, чтобы упростить переключение между контейнерами, например, используя ключевое слово auto. В будущем, если вы захотите переключиться с dequeue на queue, это будет намного проще.

2. Лямбды

В более старых версиях C ++ указатели на функции использовались для хранения поведения функции внутри переменной. Позже к функции можно было получить доступ с помощью указателя. Недостатки указателей на функции в том, что их было сложно понять и плохо читалось. Поэтому они придумали лямбды, которые заменяют традиционные указатели на функции. Все современные языки программирования, такие как Java, Kotlin, используют Lambdas.

Пример лямбда-выражения в C ++ приведен ниже.

[](){} // Empty Lambda function

Где [] представляет предложение захвата для захвата значений, () представляет параметры, переданные функции, а {} содержит тело лямбда-функции.

//Example Lambda function isOdd
auto isOdd = [](int candidate){ return candidate % 2 != 0 }; 
bool is3Odd = isOdd(3); //Returns true as 3 is Odd
bool is4Odd = isOdd(4); //Returns false as 4 is Even
vector nums{2, 3, 4, -1, 1};
//Find the number of Odd Items in the Vector. Returns 3
int odds = std::count_if(begin(nums), end(nums), isOdd);

В приведенном выше примере isOdd - это лямбда-функция, которая проверяет, является ли введенное число нечетным. Lambdas можно использовать с for_each, count_if и другими стандартными библиотечными функциями, и внезапно эти библиотеки становятся полезными с ним.

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

3. Алгоритмы стандартной библиотеки

Библиотека алгоритма в C ++ определяет функции, которые могут выполнять несколько операций, например сортировку, подсчет, манипулирование, поиск элементов в контейнерах и т. Д. Разработчику не нужно писать для них какой-либо код, и это экономит время, чтобы сосредоточиться на других частях. кода.

Пример стандартных библиотечных алгоритмов swap, sort и count_if приведен ниже.

//Example of Swap function for a and b
int a = 5;
int b = 8;
swap(&a, &b);
//Example of sort function. Sort elements in ascending order
vector<int> v{5, 3, 4, 2, 1};
sort(v.begin(), v.end());
//Count the number of 3’s in the vector v
int num_items3 = std::count_if(v.begin(), v.end(), [](int i){return i == 3;});

Можно использовать множество стандартных библиотечных алгоритмов. К преимуществам их использования относятся: они делают код более читабельным и выразительным, например, все понимают, что делает функция sort. Кроме того, отсутствие необходимости писать их с нуля экономит ваше время, усилия и всю головную боль, связанную с обработкой крайних случаев. Это также позволяет разработчику легко переключать контейнеры, поскольку большинство алгоритмов используют Итераторы для доступа к элементам. Поскольку итераторы можно использовать с любыми контейнерами, когда разработчик переходит из стека в очередь, изменения кода будут минимальными.

Самой большой проблемой для разработчика будет найти правильный алгоритм для кода и изучить его реализацию.

4. Исключения

Совершенно естественно, что программа генерирует ошибки или вызывает сбой во время выполнения. Некоторые из них могут быть предсказуемыми, некоторые - нет. Также разные типы ошибок нужно передавать по-разному. В некоторых случаях разработчик может забыть обработать случаи ошибок. Для обработки необычных и исключительных ошибок используются исключения.

Исключения в C ++ содержат 3 основных части

  • Попробовать. Этот блок должен быть как можно меньше, чтобы проверить код, который выдает исключение.
  • Throw - может вызывать исключения из класса std :: exception.
  • Catch - блок кода, используемый для перехвата исключений. Исключения необходимо упорядочить от самых конкретных исключений вверху до общих внизу.

Пример исключения показан ниже.

//Example of Divide by Zero exception thrown
void func(int a, int b)
{
  try {
    if( b == 0 ) throw std::invalid_argument("b is zero");
    else a/b;
  }
  catch(std::exception& e){
    //Handle Exception here
  }
}

Преимущества использования исключений заключаются в том, что между блоками try и catch объекты с локальной областью действия очищаются автоматически путем вызова их класса деструктора. Таким образом, блок finally не требуется в C ++, в отличие от других языков программирования. Также очень полезен класс std :: exception. Код большинства стандартных библиотек создает объекты, производные от этого класса. Также, когда существует цепочка вызовов функций, например a вызывает b, b вызывает c…. y вызывает z, возвращая ошибку от z обратно в a, это довольно неприятно. Это занимает много времени и влияет на производительность. В таких случаях исключения могут использоваться в z для обработки ошибок.

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