C++11 — одна з попередніх версій стандарту мови C++, прийнята у серпні 2011 комітетом ISO зі стандартизації мови замість ISO/IEC 14882:2003 (C++03). Новий стандарт включає доповнення в ядрі мови та розширення STL, включаючи велику частину TR1 — окрім, можливо, бібліотеки спеціальних математичних функцій.

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

ISO / IEC JTC1/SC22/WG21 Комітет Стандартизації C++ мав намір опублікувати новий стандарт в 2009 році (відповідно стандарт, який зараз називають C++0x, повинен був називатися C++09). Щоб встигнути, Комітет вирішив зосередитися на пропозиціях, що надійшли до 2006 і ігнорувати новішіThe C++ Source Bjarne Stroustrup (January 2, 2006) A Brief Look at C++0x. .

Мови програмування, такі як C++, проходять еволюційний розвиток своїх можливостей. Цей процес неминуче викликає проблеми сумісності з уже наявним кодом. Відповідно до доповіді, зробленої Б'ярном Страуструпом (автор мови С++ та член Комітету), новий стандарт буде на 100% сумісний з нинішньою версією мови С++ ^ C/C++ Users Journal Bjarne Stroustrup (May, 2005) The Design of C++0x: Reinforcing C++ 's proven strengths, while moving into the future.

Передбачувані зміни стандарту Як вже було сказано, зміни торкнуться як ядра С++, так і його стандартної бібліотеки.

При розробці кожного розділу майбутнього стандарту комітет використав ряд правил: Підтримка стабільності мови та забезпечення сумісності з C++98 і, по можливості, з Сі; Бажаним є введення нових можливостей через стандартну бібліотеку, а не через ядро мови; Бажано подавати зміни, які покращують техніку програмування; Удосконалювати C++ з точки зору системного та бібліотечного дизайну, замість введення нових можливостей, корисних для окремих програм; Збільшувати типобезпечність для запевнення безпечної альтернативи для нинішніх небезпечних підходів; Збільшувати продуктивність і можливості працювати безпосередньо з апаратною частиною; Забезпечувати рішення реальних поширених проблем; Реалізувати принцип «не платити за те, що не використовуєш»; Зробити C++ простішою для вивчення без видалення можливостей, які використовуються програмістами-експертами.

Приділяється увага новачкам, які завжди будуть становити більшу частину програмістів. Багато новачків не прагнуть поглиблювати рівень володіння С++, обмежуючись його використанням під час роботи над вузькими специфічними задачами Крім того, з огляду на універсальність С++ і широке коло її використання (включаючи як різноманітність програм, так і стилів програмування), навіть професіонали можуть виявитися новачками при використанні нових парадигм програмування.

Розширення ядра С++ Першочергове завдання комітету — розвиток ядра мови С++. Дата подання C++0x залежить від успіхів у цій частині стандарту.

Ядро буде значно вдосконаленим, буде додано підтримку багатопотоковості, підтримка узагальненого програмування, уніфікація ініціалізації та будуть проведені роботи з підвищення його продуктивності.

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

Підвищення продуктивності за рахунок ядра мови

Ці компоненти мови введені для зменшення витрат пам'яті або збільшення продуктивності.

Посилання на тимчасові об'єкти / Семантика переносу (Rvalue Reference/Move semantics) У стандарті C++ тимчасові об'єкти (оригінальний термін «R-values», оскільки вони породжуються з правого боку виразу) можна передавати у функції, але тільки як константні посилання (const &). Отже, функція не в змозі визначити, тимчасовий це об'єкт чи нормальний, який теж передали як const &. Крім того, об'єкт, переданий як const &, більше не можна модифікувати (легально).

У C++0x буде додано новий тип посилання — посилання на тимчасовий об'єкт (R-value reference). Його оголошення наступне: typename &&. Воно може бути використано як неконстантний об'єкт, який можна легально модифікувати. Це нововведення дозволяє враховувати тимчасові об'єкти і реалізовувати семантику переносу (Move semantics).

Наприклад, std::vector — це проста обгортка навколо Сі-масиву і змінної, що зберігає його розмір. Якщо std::vector створюється як тимчасовий об'єкт або повертається з функції — можна, створюючи новий об'єкт, просто перенести всі внутрішні дані із посилання нового типу. Конструктор перенесення std::vector через отримане посилання на тимчасовий об'єкт просто копіює вказівник масиву, що знаходиться в посиланні, яке після закінчення встановлюється в порожній стан.

Узагальнені константні вирази У C++ завжди була присутня концепція константних виразів. Так, вирази типу 3+4 завжди повертали одні й ті самі результати, не викликаючи жодних побічних ефектів. Самі собою вирази зі сталими надають компіляторам C++ зручні можливості для оптимізації результату компіляції. Компілятори обчислюють результати таких виразів лише на етапі компіляції і зберігають вже обчислені результати в програмі. Таким чином, подібні вирази обчислюються лише раз. Також існує кілька випадків, у яких стандарт мови вимагає використання константних виразів. Такими випадками, наприклад, можуть бути визначення масивів або значення перелічень (enum).

int GetFive () {return 5;} int some_value [GetFive() + 7]; // створення масиву 12 цілих; заборонено в C++

Вищевказаний код заборонений в C++, оскільки GetFive() + 7 фактично не є константним виразом, відомим на етапі компіляції. Компілятору на цей момент просто не відомо, що функція насправді повертає константу під час виконання. Причиною таких міркувань компілятора є те, що ця функція може вплинути на стан глобальної змінної, викликати іншу константну функцію не часу виконання тощо.

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

constexpr int GetFive () {return 5;}

int some_value [GetFive () + 7]; // створення масиву 12 цілих; дозволено в C++0x

Таке ключове слово дозволяє компілятору зрозуміти і упевнитися в тому, що GetFive повертає константу.

Використання constexpr породжує дуже жорсткі обмеження на дії функції: Така функція не може бути типу void. Тіло функції повинно бути виду return вираз . Вираз повинен також бути константою, а також може викликати лише ті функції, що також позначені ключовим словом constexpr, або просто використовувати звичайні константи. Функцію, позначену constexpr, не можна викликати до того моменту, поки вона не визначена у поточній одиниці компіляції.

Змінні також можуть бути визначені як значення константних виразів:

constexpr double accelerationOfGravity = 9.8; constexpr double moonGravity = accelerationOfGravity / 6;

Такі змінні вже неявно вважаються позначеними ключовим словом const. У них можуть міститися лише результати константних висловів чи конструктори таких виразів.

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

Зміни у визначенні простих даних (Plain Old Data або POD) У стандартному C++ лише структури, що задовольняють певному комплексу правил, можна розглядати як тип простих даних ( або POD). Існують вагомі причини очікувати розширення цих правил, для того, щоб більше типів розглядалися як POD. Типи, що задовольняють ці правилам, можна використовувати в реалізації об'єктного шару, сумісного з C. Однак, в C++03 список цих правил надмірно строгий.

C++0x послабить кілька правил, що стосуються визначення типів простих даних.

Клас / структура розглядаються як типи простих даних якщо вони тривіальні, стандартні (standard-layout???) і якщо всі їхні нестатичні члени також є типами простих даних.

Тривіальний клас чи структура задовольняють таким правилам: Вони можуть мати лише тривіальний конструктор за умовчанням. Може бути використано синтаксис конструктора за умовчанням (SomeConstructor() = default;). Вони можуть мати лише тривіальний конструктор копіювання за умовчанням. Може бути використано той самий синтаксис. Вони можуть мати лише тривіальний оператор присвоєння копії. Вони можуть мати лише тривіальний деструктор, який не повинен бути віртуальним.

Стандартний клас чи структура задовольняють такі правила: Вони можуть мати лише статичні члени не стандартних типів. Вони мають один і той же специфікатор доступу (public, private, protected) для всіх нестатичних методів. Не мають віртуальних функцій. Не мають віртуальних класів-батьків. Їхні батьківські класи можуть бути лише стандартними. Не мають батьківського класу того ж типу, що і перший оголошений невіртуальний член. Або не мають батьківських класів, що містять нестатичні методи, або не містять членів нестатичних типів у більшості класів нащадків і не більше одного батьківського класу з нестатичними членами. Іншими словами, в ієрархії класів лише один клас може містити нестатичні члени.

Прискорення компіляції мови Зовнішні шаблони У стандартному С++ компілятор повинен інстанціювати шаблон щоразу, коли зустрічає в одиниці трансляції його повну спеціалізацію. Це може істотно збільшити час компіляції, особливо в тих випадках, коли шаблон інстанційований з однаковими параметрами у великій кількості одиниць трансляції. У цей час не існує способу вказати С++, що інстанціювання проводити не повинно.

У C++0x введена ідея зовнішніх шаблонів. У С++ вже є синтаксис для вказівки компілятору того, що шаблон повинен бути інстанційованим в певній точці:

template class std::vector <MyClass>;

У С++ не вистачає можливості заборонити компілятору інстанціювати шаблон в одиниці трансляції. C++0x просто розширює даний синтаксис:

extern template class std::vector <MyClass>;

Цей вираз говорить компілятору не інстанціювати шаблон в даній одиниці трансляції.

Покращення в практичному використанні мови Ці можливості призначені для того, щоб спростити використання мови. Вони дозволяють посилити типобезпечність, мінімізувати дублювання коду, ускладнюють помилкове використання коду тощо

Списки ініціалізації Концепція списків ініціалізації прийшла в C++ з C. Ідея полягає в тому, що структура або масив можуть бути створені передачею списку аргументів в порядку, відповідному порядку визначення членів структури. Списки ініціалізації рекурсивні, що дозволяє використовувати їх для масивів структур і структур, що містять вкладені структури. Списки ініціалізації дуже корисні для статичних списків і в тих випадках, коли потрібно ініціалізувати структуру певним значенням. C++ також містить конструктори, які можуть містити загальну частину роботи з ініціалізації об'єктів. Стандарт C++ дозволяє використовувати списки ініціалізації для структур і класів за умови, що ті відповідають визначенню простого типу даних (Plain Old Data — POD). Класи, що не є POD, не можуть використовувати для ініціалізації списки ініціалізації, у тому числі це стосується і стандартних контейнерів C++, таких, як вектори.

C++0x зв'язав концепцію списків ініціалізації і шаблонний клас, названий std::initializer_list. Це дозволило конструкторам і іншим функціям отримувати списки ініціалізації як параметри. Наприклад:

class SequenceClass { public: SequenceClass (std:: initializer_list <int> list);

Цей опис дозволяє створити SequenceClass з послідовності цілих чисел таким чином:

SequenceClass someVar = {1, 4, 5, 6};