Современные возможности C++

C++ — это не просто C с классами, это очень мощный язык со многими функциями, предоставляемыми такими языками, как Python и JavaScript.

В этой статье я показал несколько функций, которые вы, возможно, знаете из Python или JavaScript, но которые вы можете использовать и в C++!!

Эта статья предназначена для людей с базовыми знаниями C++.

Оглавление

  • Шаблоны
  • Авто
  • Функция переменного аргумента
  • Стандартная библиотека шаблонов
  • Цикл на основе диапазона
  • Лямбда-выражения

Шаблоны

Предположим, вы хотите написать функцию с одинаковыми операциями для разных типов данных.

В Python это просто, поскольку одна и та же переменная может указывать на разные объекты разных типов. Таким образом, вы можете повторно использовать один и тот же код для всех типов.

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

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

Давайте посмотрим на пример:

  • Шаблонная функция для получения максимум двух значений, значение может быть любого типа данных.
#include <iostream>
template <typename type>    // Creating a template
type max(type first, type second)
{
    return first > second ? first : second;
}
int main()
{
    std::cout << max<int>(2, 3) << "\n";     // 3
    std::cout << max(3.4f, 4.2f) << "\n";    // 4.2
    std::cout << max('C', 'S') << "\n";      // S
return 0;
}
  • Первый вызов скажет компилятору создать функцию с заменой type на int.
  • Точно так же второй и третий вызовы создадут функцию с заменой type на float и char.
  • В первом вызове мы явно указали компилятору, что это тип int с нотацией <type>.

Аналогичным образом вы можете создавать шаблоны для классов.

Чтобы узнать больше о шаблонах в C++, ознакомьтесь с этой статьей.

Авто

Вы можете вывести тип переменной во время компиляции, используя ключевое слово auto.

Это полезно, когда переменная имеет сложный тип.

Вот пример auto

#include <iostream>
#include <string>
int main()
{
    auto an_int = 50;
    auto a_float = 10.5f;
    auto a_double = 100.12;
    auto a_char = 'S';
    auto a_string = "String";
    std::cout << an_int << "\n";        // 50
    std::cout << a_float << "\n";        // 10.5
    std::cout << a_double << "\n";        // 100.12
    std::cout << a_char << "\n";        // S
    std::cout << a_string << "\n";        // String
    return 0;
}

Чтобы узнать больше об auto в C++, прочитайте эту статью

Функции переменных аргументов

Если вы знаете Python, то наверняка использовали * для создания функции с переменным числом аргументов.

Вы можете сделать то же самое в C++, используя многоточие и вариативные шаблоны.

Давайте разберемся с этим на примере -

#include <iostream>
template <typename type>
int sum(type n)
{
    return n;
}
template <typename first, typename... types>    // Packing Arguments
int sum(first n, types ...args)        // Expanding Arguments
{
    return n + sum(args...);    
}
int main()
{
    int sum3 = sum(1,2,3);
    std::cout << sum3 << "\n";        // 6
    int sum5 = sum(1,2,3,4,5);
    std::cout << sum5 << "\n";        // 15
    return 0;
}

Здесь ... после typename упаковывает все аргументы, переданные при вызове, в types, а затем мы снова их распаковываем с ... перед args.

Затем мы использовали рекурсию для вызова функции с аргументами на единицу меньше исходного.

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

#include <iostream>
template <typename First>
void print(First first)
{
    std::cout << first << "\n";
}
template <typename First, typename ... Types>
void print(First first, Types ... args)
{
    std::cout << first << " ";
    print(args...);
}
int main()
{
    print("One", "Two");
    print("One", "Two", "Three", "Four");
    return 0;
}

Узнайте больше о многоточии и вариативных шаблонах в этой статье.

Стандартная библиотека шаблонов

В C++ встроено только несколько примитивных типов данных, в отличие от Python, который предоставляет динамический список, словарь, множество и кортежи и т. д.

Стандартная библиотека шаблонов (STL) — это программная библиотека для C++, которая предоставляет такие структуры данных и алгоритмы.

STL предоставляет следующие четыре компонента:

  • Алгоритмы: поиск, сортировка и т. д.
  • Контейнеры: последовательности, такие как вектор, список. Очередь, стек, карта, набор и т. д.
  • Функции
  • Итераторы

Она называется библиотекой шаблонов, потому что использует описанную выше функцию шаблонов C++.

Давайте посмотрим на один пример контейнера: вектор.

Вектор

Класс STL vector — это шаблон класса для контейнеров последовательности.

Он хранит элементы заданного типа в линейном порядке и обеспечивает быстрый произвольный доступ к любому элементу. Похоже на массив? Да, это массив, но он динамический, т. е. его размер может изменяться при необходимости.

В этом примере показано, как создать и использовать вектор:

#include <iostream>
#include <vector>    // STL Header file for vector class
int main()
{
    std::vector<int> numbers{1, 2, 3, 4, 5};
    for (int i = 0; i < numbers.size(); i++)
        std::cout << numbers[i] << " ";
    std::cout << "\n";  // OUTPUT: 1 2 3 4 5
    std::vector<char> alphabets;    // Empty vector
    alphabets.push_back('a');    // adding an element to back of vector
    alphabets.push_back('b');
    alphabets.push_back('c');
    std::cout << alphabets[1] << "\n";  // OUTPUT: b
    return 0;
}

Чтобы узнать больше о STL, ознакомьтесь с этой статьей.

Цикл на основе диапазона

В предыдущем примере мы использовали простой цикл for для перебора нашего вектора. Мы можем сделать то же самое с лучшим циклом for на основе диапазона.

Синтаксис:

for (for-range-declaration : expression)
    statement

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

// For printing the numbers vector
for (int x : numbers)
    std::cout << x << " ";
// For printing the alphabets vector
for (auto ch : alphabets)    // Notice the use of auto - Recommended
    std::cout << ch << " ";
for (auto i : {1, 2, 3})
        std::cout << i << " ";    // 1 2 3
int arr[] = {4, 5, 6};
for (auto j : arr)
    std::cout << j << " ";    // 4 5 6

Здесь x будет указывать на отдельный элемент в numbers один за другим.

Чтобы узнать больше о циклах на основе диапазона, прочитайте эту статьюe.

Лямбда-выражения

Лямбда-выражение — это удобный способ определения анонимной функции.

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

Синтаксис:

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

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

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

изменяемая спецификация (необязательно): ключевое слово mutable позволяет нам изменять значение, полученное в теле лямбда-выражения. (Использование показано в примере ниже).

спецификация-исключения(необязательно): вы можете использовать спецификацию исключения noexcept, чтобы указать, что лямбда-выражение не создает никаких исключений.

trailing-return-type (необязательно): как и обычная функция, лямбда также имеет возвращаемый тип. Вы можете опустить возвращаемую часть лямбда-выражения, если тело лямбда-выражения содержит только один оператор возврата или выражение не возвращает значение.

тело лямбда: тело лямбда может содержать все, что может содержать тело обычной функции.

Вот несколько примеров лямбда-функций:

  • Здесь мы использовали лямбда-функцию, которая находит квадрат числа. Тип лямбды автоматически выводится с помощью auto и сохраняется в идентификаторе square. Тип возвращаемого значения автоматически выводится как int.
#include <iostream>
int main()
{
    auto square = [](int n) {
      return n * n;  
    };
std::cout << "Square of 2 = " << square(2) << "\n";
    // Square of 2 = 4
return 0;
}
  • Здесь мы показали использование ключевого слова mutable, без него мы получили бы сообщение об ошибке, говорящее, что outer доступно только для чтения. Более того, значение outer не изменилось за пределами лямбды, поскольку оно было захвачено значением [=].
#include <iostream>
int main()
{
    int outer = 50;
auto fn = [=]() mutable {
        outer = 100;    // OK, because of mutable
        std::cout << "Outer = " << outer << "\n";   // Outer = 100
    };
fn();
    std::cout << "Outer = " << outer << "\n";   // Outer = 50
return 0;
}
  • Здесь мы использовали лямбда для передачи функции алгоритму for_each.
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
    std::vector<int> nums{1, 2, 3, 4, 5, 6};
for (auto x : nums) // 1 2 3 4 5 6 
        std::cout << x << " ";
    std::cout << "\n";
// Square every number
    std::for_each(begin(nums), end(nums), [](int& n) {n = n * n;});
for (auto x : nums) // 1 4 9 16 25 36 
        std::cout << x << " ";
    std::cout << "\n";
return 0;
}

Чтобы узнать больше о лямбда-функциях, ознакомьтесь с этой статьей.

EndNote

Эта статья должна была познакомить вас с некоторыми современными мощными функциями, предоставляемыми языком C++.

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

C++ обладает более удивительными и современными функциями, вопреки мнению, что это старый и устаревший язык.

Поделитесь своим мнением в комментариях.

Спасибо за чтение

Вам также может понравиться:

Эта статья была первоначально опубликована в Блоге Yuvraj’s CS.

Свяжитесь со мной в Twitter, GitHub и LinkedIn.