Деякі чудові сучасні можливості на C ++, які повинен знати кожен розробник

Як мова, C ++ багато еволюціонував.

Звичайно, це не сталося за одну ніч. Був час, коли на C ++ бракувало динамізму. Захоплюватися мовою було важко.

Але все змінилося, коли стандартний комітет С ++ вирішив закрутити колесо.

Починаючи з 2011 року, C ++ виникла як динамічна та постійно розвивається мова, на яку сподівалися багато людей.

Не подумайте неправильно, що мова стала простішою. Це все ще одна з найскладніших мов програмування, якщо не найскладніша, які широко використовуються. Але C ++ також став набагато зручнішим для користувачів, ніж його попередні версії.

У своєму останньому дописі я розповів про бібліотеку алгоритмів C ++, яка збагатилася за останні пару років.

Сьогодні ми розглянемо деякі нові можливості (починаючи з C ++ 11, якому до речі вже 8 років), які хотів би знати кожен розробник.

Також зауважте, що я пропустив деякі розширені функції в цій статті, але я готовий писати про них у майбутньому. ? ️

Іди!

Ключове слово auto

Коли C ++ 11 було вперше представлено auto, життя стало простішим.

Ідея autoполягала в тому, щоб змусити компілятор C ++ визначати тип ваших даних під час компіляції - замість того, щоб змушувати вас оголошувати тип щоразу. Це було так зручно, коли у вас є типи даних, такі як nt, int >>>?map

Original text


Подивіться на рядок номер 5. Ви не можете декларувати щось без символу initializer. Це насправді має сенс. Рядок 5 не дає компілятору знати, яким може бути тип даних.

Спочатку autoбув дещо обмежений. Тоді в пізніших версіях мови до неї додалося більше сили!

У рядках 7 та 8 я використовував ініціалізацію в дужках. Це також була нова функція, додана в C ++ 11.

Пам'ятайте, у випадку використання autoкомпілятор повинен мати спосіб визначити ваш тип.

Тепер дуже приємне запитання, що станеться, якщо ми напишемоauto a = {1, 2, 3} ? Це помилка компіляції? Це вектор?

Власне, C ++ 11 представив pe>. Скорочений ініціалізований список буде вважатися цим полегшеним контейнером, якщо його буде автоматично.std::initializer_listlare

Нарешті, як я вже згадував, виведення типів компілятором може бути дійсно корисним, коли у вас є складні структури даних:

Не забудьте перевірити рядок 25! Вираз auto [v1,v2] = itr.secondбуквально є новою функцією в C ++ 17. Це називається структурованим прив'язуванням . У попередніх версіях мови потрібно було витягувати кожну змінну окремо. Але структурована прив'язка зробила це набагато зручнішим.

Більше того, якщо ви хочете отримати дані за допомогою посилання, ви просто додасте символ - auto &[v1,v2] = itr.second.

Охайний.

Лямбда-вираз

C ++ 11 представив лямбда-вирази, щось на зразок анонімних функцій у JavaScript. Вони є функціональними об'єктами, без будь-яких імен, і вони фіксують змінні в різних сферах на основі деякого стислого синтаксису. Вони також можна призначити змінним.

Лямбди дуже корисні, якщо вам потрібно виконати якусь невелику швидку справу всередині вашого коду, але ви не бажаєте писати для цього цілу окрему функцію. Іншим досить поширеним використанням є використання їх як функцій порівняння.

Наведений приклад має багато що сказати.

По-перше, зверніть увагу, як ініціалізація фігурних дужок піднімає вагу для вас. Далі йде загальний, begin(), end()який також є доповненням до C ++ 11. Потім з’являється лямбда-функція як компаратор для ваших даних. Оголошено параметри лямбда-функціїautoякий був доданий в C ++ 14. До цього ми не могли використовувати autoпараметри функції.

Зверніть увагу, як ми починаємо лямбда-вираз із квадратної дужки []. Вони визначають сферу дії лямбда - скільки повноважень вона має над локальними змінними та об'єктами.

Як визначено у цьому чудовому сховищі на сучасному C ++:

  • [] - нічого не захоплює. Отже, ви не можете використовувати будь-яку локальну змінну зовнішньої області всередині вашого лямбда-виразу. Ви можете використовувати лише параметри.
  • [=]- фіксує локальні об’єкти (локальні змінні, параметри) в обсязі за значенням. Ви можете ними користуватися, але не можете їх змінювати.
  • [&] - фіксувати локальні об’єкти (локальні змінні, параметри) в області дії за допомогою посилання. Ви можете їх змінити. Як наступний приклад.
  • [this]- захоплення thisпокажчика за значенням.
  • [a, &b]- захоплювати об’єкти aза значенням, bза посиланням.

Отже, якщо всередині вашої лямбда-функції ви хочете перетворити свої дані в інший формат, ви можете використовувати лямбда, скориставшись перевагами масштабування. Наприклад:

У наведеному вище прикладі, якщо ви захопили локальні змінні за значенням ( [factor]) у своєму лямбда-виразі, ви не зможете змінити factorрядок 5. Оскільки просто, ви не маєте права цього робити. Не зловживайте своїми правами! ?

Нарешті, зауважте, що ми беремо valза посилання. Це гарантує, що будь-яка зміна всередині лямбда-функції насправді змінює vector.

Введіть оператори всередині if & switch

Мені дуже сподобалась ця функція C ++ 17 одразу після того, як я про неї дізнався.

Очевидно, тепер ви можете зробити ініціалізацію змінних і перевірити стан на цьому - одночасно всередині if/switchблоку. Це дійсно корисно, щоб ваш код був стислим і чистим. Загальна форма:

if( init-statement(x); condition(x)) { // do some stuff here } else { // else has the scope of x // do some other stuff }

Зробіть це за час компіляції constexpr

constexpr це круто!

Скажімо, у вас є якийсь вираз для оцінки, і його значення не зміниться після ініціалізації. Ви можете попередньо обчислити значення, а потім використовувати його як макрос. Або як пропонується C ++ 11, ви можете використовувати constexpr.

Програмісти, як правило, максимально скорочують час виконання своїх програм. Отже, якщо є деякі операції, які ви можете змусити компілятор виконати і зняти навантаження з середовища виконання, тоді час виконання можна покращити.

Наведений вище код є дуже поширеним прикладом constexpr.

Оскільки ми оголосили функцію обчислення Фібоначчі як constexpr, компілятор може попередньо обчислитиfib(20)під час компіляції. Тож після компіляції він може замінити рядок

const long long bigval = fib(20);з

const long long bigval = 2432902008176640000;

Зверніть увагу, що переданий аргумент є constзначенням. Це один важливий момент оголошених функцій constexpr- передані аргументи також повинні бути constexprабо const. В іншому випадку функція буде поводитися як звичайна функція, що означає відсутність попереднього обчислення під час компіляції.

Змінні також можуть бути constexprтеж. У цьому випадку, як ви можете здогадатися, ці змінні повинні бути оціненими під час компіляції. В іншому випадку ви отримуєте помилку компіляції.

Цікаво, що пізніше в C ++ 17 constexpr-ifтаconstexpr-lambdaбули введені.

Кортежі

Так само, як pair, tupleявляє собою набір значень фіксованого розміру різних типів даних.

Іноді його зручніше використовувати std::arrayзамість tuple. arrayподібний до простого масиву типу С разом із кількома функціональними можливостями стандартної бібліотеки С ++. Ця структура даних була додана в C ++ 11.

Виведення аргументу шаблону класу

Дуже багатослівна назва об’єкта. Ідея полягає в тому, що з C ++ 17, вирахування аргументів для шаблонів також відбуватиметься для стандартних шаблонів класів. Раніше він підтримувався лише для шаблонів функцій.

Як результат,

std::pair user = {"M", 25}; // previous std::pair user = {"M", 25}; // C++17

Тип відрахування здійснюється неявно. Це стає ще зручнішим для tuple.

// previous std::tuple user ("M", "Chy", 25); // deduction in action! std::tuple user2("M", "Chy", 25);

Ця функція вище не матиме сенсу, якщо ви не зовсім знайомі з шаблонами C ++.

Розумні вказівники

Покажчики можуть бути пекельними.

Завдяки свободі, яку такі мови, як C ++, надають програмістам, іноді стає дуже легко застрілити собі ногу. І в багатьох випадках покажчики несуть відповідальність за шкоду.

На щастя, C ++ 11 представив розумні вказівники, вказівники, які є набагато зручнішими, ніж необроблені вказівники. Вони допомагають програмістам запобігти витоку пам'яті, звільняючи її, коли це можливо. Вони також забезпечують безпеку виключень.

Я думав написати у цій публікації про розумні вказівники на C ++. Але, мабуть, про них є багато важливих деталей. Вони заслуговують на свою власну посаду, і я, безумовно, готовий написати про них найближчим часом.

Це все на сьогодні. Пам'ятайте, що C ++ насправді додав набагато новіші функції в останні версії мови. Вам слід ознайомитися з ними, якщо вам цікаво. Ось чудове сховище сучасного C ++, яке буквально називається Awesome Modern C ++!

Адіос!