Поддержка стандарта C++0x в Visual Studio 2010

среда, 7 июля 2010, Yuriy Bogomolov

C++0x — будущая версия стандарта языка C++, вместо ныне существующего ISO/IEC 14882:2003. На текущий момент доступен C++0x Technical Report 1 (TR1).

В последней версии Microsoft Visual Studio 2010 есть поддержка небольшой части разрабатываемого стандарта, а именно:

1. Выведение типов и ключевое слово auto

 Можно объявлять переменные с неявным указанием типов:

int explicitTypedVar = 42;
decltype(explicitTypedVar) implicitTypedVar = 100500;

 Ключевое слово auto, по сути, является аналогом var в C#:

auto doubleExplVar = 0.5;
auto intExplVar = 0;

 Данное ключевое слово особенно полезно при работе с шаблонами и итераторами, вместо:

for (vector<int>::const_iterator itr = myvec.begin(); itr != myvec.end(); ++itr) { do something; }

можно написать более кратко:

for (auto itr = myvec.begin(); itr != myvec.end(); ++itr) { do something; }

Если же вам во время разработки придется поменять тип myvec на, к примеру, vector> — вам не надо будет волноваться о замене типов всех объявленных итераторов, поскольку об этом побеспокоится компилятор благодаря ключевому слову auto.

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

Благодаря поддержке выведения типов появилась возможность объявлять и использовать лямбда-функции. Выглядит это примерно таким образом:

auto lambdaFunc = [](int x) { return x + 1; };
int incrementedOne = lambdaFunc(1);

Синтаксис объявления таков:

<тип> <имя функции> = [<модификаторы связывания>](<список аргументов>){ <тело функции> };

Модификаторы связывания позволяют предоставить внутри тела функции доступ:

  1. ко всем объявленным выше переменным по ссылке при помощи модификатора &;
  2. ко всем объявленным выше переменным по значению при помощи модификатора =;
  3. к определенной переменной при помощи указания ее имени после модификатора = или &;
  4. для доступа к указателю this его надо явно указать в качестве модификатора.

Небольшой пример с комментариями:

int a = 0;
int b = 1;
auto lambda1 = [&](int x){ a = x; }; // возвращаемый тип — void
lambda1(10); // теперь a = 10
auto lambda2 = [=](int x){ return x + b; }; // возвращаемый тип — int
int tempX = lambda2(10); // tempX = 10 + 1 = 11
auto lambda3 = [&a, b](int x) { a += x + b; }; // возвращаемый тип — int
lambda3(10); // теперь a = 10 + 10 + 1 = 21
auto lambda4 = [this]{ this->SomeMethod(); }; // корректнай вызов метода SomeMethod()

 Детальнее — в Википедии.

3. Макропредикат static_assert()

Данный предикат позволяет проводить проверку на выполнение определенного условия по время компиляции, в противовес стандартному assert(expression), которая вызывается во время исполнения программы:

const int ANSWER = 41;
assert(ANSWER == 42); // нормально скомпилируется, упадет при запуске с R6010 — Assertion failed
static_assert(ANSWER == 42, "ANSWER not equals 42!"); // не скомпилируется из-за error C2338: ANSWER not equals 42!

4. Новая система инициализации списков

const int testArray[] = { 1, 2, 3, 4, 5};

 Увы, инициализировать таким образом std::vector или std::list у меня не получилось, хотя в стандарте описана такая возможность.

5. Rvalue references

В C++ временные переменные (называемые rvalues, т.к. они часто находятся в правой части выражения) не отличимы от типов const T&. C++0x вводит новый ссылочный тип, называемый «ravlue reference», описываемый как T&&.

Например, std::vector внутренне является оболочкой над массивом с известной длиной. Если std::vector создается или возвращается функцией, он может быть сохранен только при помощи создания нового std::vector и копировании всех данных возвращенного вектора в новый вектор. После чего временный вектор уничтожается с удалением его данных. При помощи нового rvalue reference, так называемый «move constructor» может просто-напросто скопировать указатель на внутренний массив возвращенного вектора в вектор, которому присваивается это значение. При этом не происходит копирования данных и лишнего выделения памяти, что благоприятно сказывается на производительности. Для использования этой функциональности необходимо, чтобы функция возвращала std::vector&&. Если же std::vector (или, соответственно, ваш тип) не содержит move constructor, будет вызван обычный конструктор копирования.

В теории, просто скомпилировав вашу программу с помощью нового компилятора C++0x, вы можете получить значительный прирост производительности.

В целом, это тема для отдельной статьи, подробнее — здесь.

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

Компании из статьи


Microsoft Украина


Сайт:
http://www.microsoft.com/ukr/ua/

Microsoft Украина Украинское подразделение компании Microsoft.

Ищите нас в интернетах!

Комментарии

Свежие вакансии