[Перевод] Изменения в Visual C++10.05.2015 22:33
Когда вы захотите обновить версию Visual C++ компилятора (например, перейти с Visual Studio с 2013 на 2015), будет не лишним узнать, почему вы можете столкнуться с тем, что код, который прежде успешно компилировался и выполнялся, теперь будет вызывать ошибки компиляции и/или ошибки времени выполнения.Эти проблемы могут быть вызваны многочисленными изменениями компилятора для соответствия стандарту С++, изменениями в сигнатурах функций или изменениями расположения объектов в памяти.Для того, чтобы избежать ошибок времени выполнения (их, как известно, наиболее трудно найти), мы рекомендуем никогда не делать статическое связывание с двоичными файлами, полученными другой версией компилятора. Также при обновлении своей программы (EXE или DLL), убедитесь, что используемые библиотеки тоже собраны новой версией компилятора.Если вы используете типы из CRT (C Runtime) или STL (Standart Template Library), не передавайте их между двоичными файлами (включая DLL), которые собраны разными версиями компилятора. Более подробно этот вопрос рассмотрен в Potential Errors Passing CRT Objects Across DLL Boundaries.И в дальнейшем мы рекомендуем не писать код, который зависит от конкретного расположения объектов в памяти (если это не COM интерфейс или POD объект). Если у вас сейчас есть такой код, после обновления компилятора вам следует убедиться, что все работает как надо. Более подробно можно почитать здесь: Portability At ABI Boundaries (Modern C++).
Ниже в статье описываются изменения в компиляторе Visual C++ (который идет с Visual Studio 2015 Preview). В статье слова «новое поведение» и «сейчас» относятся именно к этой версии, а «старое поведение» и «раньше» — к Visual Studio 2013 (и более ранним версиям).
Краткое содержание: — Изменения в компиляторе— Изменения в C Runtime Library (CRT)— Изменения в STL— Изменения в MFC и ATL
Изменения в компиляторе/Zc: forScope — Флаг компилятора /Zc: forScope- объявлен устаревшим (deprecated) и в будущем будет удален. Сейчас компилятор при использовании этого флага будет выкидывать предупреждение D9035.Данный флаг используется для использования нестандартного расширения С++ — использование переменных, объявленных в описании цикла for за пределами этого цикла. Этот флаг необходим только если установлен другой флаг — /Za (соответствовать стандарту), потому что без /Za, использование переменных из описания цикла по умолчанию разрешено. Если вам не нужно заботиться о кроссплатформенности (например, не предполагается собирать код другими компиляторами), вы можете выключить флаг /Za (установить свойству проекта «Disable Language Extensions» значение «No»). Если же вы заботитесь о кроссплатформенности и соответствия стандарту, значит такие участки кода нужно переписать, переместив объявление переменной выше цикла:
// zc_forScope.cpp
// compile with: /Zc: forScope- /Za
// C2065 expected
int main () {
// Раскомментить следующую строку для исправления ошибки
// int i;
for (int i =0; i < 1; i++)
;
i = 20; // с флагом /Za переменная i здесь уже вне своего блока
}
/ZgФлаг компилятора /Zg (создание прототипов функций) больше недоступен для использования (раньше у него был атрибут deprecated)
Теперь нельзя запустить юнит-тесты, использующие C++/CLI, из командной строки используя mstest.exe, взамен нужно использовать vtest.console.exe. Более подробно можно узнать об этом здесь: VSTest.Console.exe command-line options.
Ключевое слово mutableТеперь использование mutable, в соответствии со стандартом, допускается только применимо к именам членов класса, и не может быть применено к ссылкам, или именам, объявленным как const или static. Пример:
struct S {
mutable int &r;
};
Раньше это компилировалось, теперь компилятор выдаст ошибку С2071. Для исправления, нужно просто убрать mutable.
char_16_t и char_32_tТеперь нельзя использовать char_16_t и char_32_t в качестве псевдонимов пользовательских типов, потому что сейчас эти типы определяются как встроенные. Раньше было довольно распространенной практикой для авторов библиотек определять char_16_t и char_32_t в качестве псевдонимов для uint_16_t и uint_32_t, соответственно.
#include
typedef uint16_t char16_t; //C2628
typedef uint32_t char32_t; //C2628
int main (int argc, char* argv[])
{
uint16_t x = 1; uint32_t y = 2;
char16_t a = x;
char32_t b = y;
return 0;
}
Для исправления нужно убрать объявление псевдонимов и переименовать любые другие идентификаторы конфликтующие со вновь введенными.
Нетиповые (non-type) параметры шаблоновКод, включающий в себя нетиповые параметры шаблонов сейчас правильно проверяется на совместимость типов. Например, следующий код раньше компилировался без ошибок:
struct S1
{
void f (int);
void f (int, int);
};
struct S2
{
template void f () {}
};
void f ()
{
S2 s2;
s2.f();
}
Сейчас компилятор выдаст ошибку, так как тип параметра шаблона не соответствует типу переданного аргумента (тип параметра — указатель на константный метод, но f не является константной).error C2893: Failed to specialize function template 'void S2:: f (void)'note: With the following template arguments: note: 'C=S1'note: 'Function=S1:: f’Для избавления от этой ошибки убедитесь, что тип аргумента шаблона полностью соотвествует типу параметра.
__declspec (align)Компилятор больше не принимает __declspec (align) для функций. По правде говоря, он никогда и не принимал, но сейчас он будет выдавать ошибку С3323. Для избавления от нее просто уберите это выражение из объявления функции. Так как это и раньше не имело никакого эффекта, это не поменяет ничего в вашей программе.
Обработка исключенийВ обработке исключений произошло несколько изменений. Первое — объекты-исключения должны быть копируемыми и перемещаемыми. раньше подобный код компилировался, теперь будет ошибка:
struct S {
public:
S ();
private:
S (const S &);
};
int main ()
{
throw S (); // error
}
Проблема здесь в том, что конструктор копирования объявлен приватным, таким образом, объект не может быть скопирован, что обычно требуется при обработке исключения. То же самое применимо в случае, когда конструктор объявлен explicit.
struct S {
S ();
explicit S (const S &);
};
int main ()
{
throw S (); // error
}
Для избавления от этой проблемы убедитесь, что конструктор для объекта исключения объявлен в публичной зоне и explicit.При ловле исключения также требуется, чтобы объект был копируемым. Следующий код скомпилируется в ранних версиях Visual Studio, но сейчас будет ошибка:
struct B {
public:
B ();
private:
B (const B &);
};
struct D: public B {
};
int main ()
{
try
{
}
catch (D d) // error
{
}
}
Эту ошибку можно исправить, приняв исключение по ссылке:
catch (D& d)
{
}
Строки и макросыСейчас компилятор поддерживает определенные пользователем литералы (user defined literals — UDL). Как следствие этого, строки (точнее строковые литералы), за которыми без пробела поставлен макрос, интерпретируются как UDL, что может явиться причиной ошибки или неожиданного результата. Например, раньше это компилировалось без проблем:
#define _x «there»
char* func () {
return «hello»_x;
}
int main ()
{
char * p = func ();
return 0;
}
Компилятор интрепретировал возвращаемое функцией func значение как строку «hello», и макрос, который раскрывался в «there», а затем соединял два этих литерала в один. Сейчас компилятор интерпретирует это как UDL, но так как не может найти определение _х среди известных ему UDL, он выдает ошибку: error C3688: invalid literal suffix '_x'; literal operator or literal operator template 'operator »_x' not foundnote: Did you forget a space between the string literal and the prefix of the following string literal? Для решения этой проблемы нужно поставить пробел между строкой и макросом.
Строки, расположенные рядомТак же, как и в предыдущем случае, из-за изменений в разборе строк, строящие рядом строковые литералы, которые не разделяет пробел, раньше интерпретировались как одна строка, а сейчас для корректной компиляции нужно добавить пробел:
char * str = «abc«def»;
Просто добавьте пробел между строками:
char * str = «abc» «def»;
Размещающий new и deleteДля соответствия стандарту С++14 было изменено поведение оператора delete. Детали можно прочитать в C++ Sized Deallocation. Была добавлена форма глобального оператора delete, которая принимает размер объекта. Важность этого изменения в том, что если в вашем коде есть оператор delete с такой же сигнатурой (соответствующая размещающему оператору new), вы получите ошибку компиляции (С2956, которая указывает на строку с использованием оператора new, так как именно в этом месте компилятор пытается определить подходящий оператор delete).Функция void operator delete (void*, size_t) была размещающим оператором delete, соответствующим функции размещающего оператора new — void* operator new (size_t, size_t) из С++11. В новом стандарте С++14 этот delete стал обычной функцией деаллокации (то есть глобальным оператором delete). Стандарт требует следующего — если размещающий new ищет соответствующий delete и находит стандартную функцию, программа не скомпилируется.Например, предположим, ваш код определяет размещающий new и delete:
void * operator new (std: size_t, std: size_t);
void operator delete (void*, std: size_t) noexcept;
Проблема здесь в следующем: совпадение описания оператора размещающего delete и описания нового глобального оператора. Для того, чтобы избежать такого совпадения, можно использовать тип, отличный от size_t, при описании размера в размещающих операторах new и delete. Здесь нужно принять во внимание, что size_t зависит от компилятора, в Visual C++ это псевдоним для unsigned int. Хорошим решеним здесь будет использование перечисления:
enum class my_type: size_t {};
Затем, нужно изменить объявления размещающих операторов new и delete так чтобы вторым параметром вместо size_t они принимали my_type. Также нужно будет подправить передачу аргумента в вызов new (например, с использованием static_cast:: (void)': attempting to reference a deleted functionnote: compiler has generated ':: ' hereДля решения этой проблемы, нужно определить свой конструктор и/или деструктор
struct S {
// Определяем конструктор по умолчанию, добавляя пустое тело
S () {}
};
union {
struct {
S s;
};
} u;
Объединения с анонимными структурамиДля того, чтобы обеспечить соответствие стандарту, было изменено поведение времени выполнения для членов анонимных структур в объединениях. Конструктор анонимных структур — членов объединений больше не вызывается неявно при создании объединения. Также деструктор таких полей не вызывается неявно при выходе объединения из блока видимости. Пример:
#include
struct S {
S () { printf («Creating S\n»); }
~S (){ printf («Destroying S\n»); }
};
union U {
struct {
S s;
};
U () {}
~U (){}
};
void f ()
{
U u;
// Неявный вызов деструктора
}
int main ()
{
f ();
char s[1024];
printf («Press any key.\n»);
gets_s (s);
return 0;
}
Раньше вызывался и конструктор и деструктор. Сейчас они не вызываются. Компилятор выдает предупреждения: warning C4587: 'U: s': behavior change: constructor is no longer implicitly calledwarning C4588: 'U: s': behavior change: destructor is no longer implicitly calledДля восстановления старого поведения нужно дать имя анонимной структуре. поведение времени выполнения неанонимных структур остается независимой от версии компилятора.
#include
struct S {
S () { printf («Creating S.\n»); }
~S () { printf («Destroying S\n»); }
};
union U {
struct {
S s;
} namedStruct;
U () {}
~U () {}
};
void f ()
{
U u;
}
int main ()
{
f ();
char s[1024];
printf («Press any key.\n»);
gets_s (s);
return 0;
}
В качестве альтернативного решения можно попытаться перенести код конструктора и деструктора структуры в новые методы и вызывать их из конструктора и деструктора объединения:
#include
struct S {
void Create () { printf («Creating S.\n»); }
void Destroy () { printf («Destroying S\n»); }
};
union U {
struct {
S s;
};
U () { s.Create (); }
~U () { s.Destroy (); }
};
void f ()
{
U u;
}
int main ()
{
f ();
char s[1024];
printf («Press any key.\n»);
gets_s (s);
return 0;
}
Разрешение шаблонов (template resolution)В разрешение имен для шаблонов также были внесены изменения. В С++, при рассмотрении кандидатов при разрешении имен, вполне возможен случай когда одно или более имен могут быть неверными конкретизациями (invalid instantiation) шаблона. Эти неверные реализации обычно не вызывают ошибок компиляции (т.к. используется принцип, известный как SFINAE).Сейчас, если SFINAE требует от компилятора конкретизировать шаблон класса, любые ошибки во время выполнения этой конкретизации будут считаться ошибками компилятора. Раньше эти ошибки игнорировались. Например:
#include
template
struct S
{
S () = default;
S (const S&);
S (S&&);
template:: value>:: type>
S (S&&);
};
struct D;
void f1()
{
S s1;
S s2(s1);
}
struct B
{
};
struct D: public B
{
};
void f2()
{
S s1;
S s2(s1);
}
Новый компилятор выдаст следующее сообщение об ошибке: type_traits (1110): error C2139: 'D': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_base_of'…\t331.cpp (14): note: see declaration of 'D'…\t331.cpp (10): note: see reference to class template instantiation 'std: is_base_of' being compiled
with
[
T=D,
U=D
]
Причина ошибки в том, что в месте первого вызова is_base_of класс D еще не определен.В этом случае исправление ошибки будет следующим: не нужно использовать такие проверки типов до определения классов, значит нужно перенести определение B и D d в начало файла. Если эти определения в заголовочных файлах, нужно проверить порядок включения чтобы убедиться, что определения классов включаются раньше, чем используется проблемный шаблон.
Конструкторы копированияИ в Visual Studio 2013 и в Visual Studio 2015 RC, компилятор создает конструктор копирования для класса, если в этом классе есть определенный пользователем конструктор перемещения, но нет определенного пользователем конструктора копирования. В Dev14 этот неявно генерируемый конструктор копирования помечается как »=delete».
Изменения в C Runtime Library (CRT)
Общие изменения
Рефакторинг бинарных файловБиблиотека CRT была разделена на два бинарных файла — на общая библиотеку CRT (Universal CRT — ucrtbase), которая содержит бОльшую часть стандартной функциональности, и библиотеку VC Runtime (vcruntime140), которая содержит зависимую от компилятора функциональность (например, обработка исключений и встроенные функции (intrinsics)). Если вы используете стандартные настройки проекта, тогда это изменение вас никак не затронет, так как компоновщик сам станет использовать эти новые библиотеки. Если же вы устанавливали свойство компоновщика проекта Ignore All Default Libraries в Yes, или вы использовали флаг линковщика /NODEFAULTLIB, тогда вам следует обновить свой список библиотек (свойство проекта Additional Dependencies), то есть включить в него новые библиотеки самому. А точнее — заменить старые CRT библиотеки (libcmt.lib, libcmtd.lib, msvcrt.lib, msvcrtd.lib) на новые эквиваленты. Для каждой из двух новых библиотек есть статическая (.lib) и динамическая (.dll) версии, а также релизная сборка (без суффикса) и отладочная (с суффиксом «d»). Более подробно здесь: CRT Library Features
localeconvФункция localeconv, объявленная в locale.h теперь работает корректно в случаях когда включена потоковая локаль (per-thread locale). Раньше эта функция возвращала Iconv глобальной, а не потоковой, локали.Если вы используете потоковую локаль, вам следует проверить, как новое поведение localeconv повлияет на вашу программу.
С++ перегрузка библиотечных функцийРаньше в перегружались некоторые, но не все, математические библиотечные функции. В была определена перегрузка остальных функций. Это вело к проблемам разрешения перегрузки, если включен только . Теперь все перегрузки перенесены из в .
Приведение в соответствие стандарту чисел с плавающей точкойВ математической библиотеке было сделано много изменений для приближения к соответствию стандарту IEEE-754 и Приложению F стандарта C11, основное внимание было уделено особым случаям (NaN и бесконечности). Например, при передаче в функцию библиотеки NaN раньше часто возникала ошибка, сейчас — не возникает. Более подробно узнать об этом можно здесь: IEEE 754 Standard, Annex F of the C11 Standard.Эти изменения не вызовут ошибок времени компиляции, однако программа может начать вести себя по другому — более соответственно стандартам.
FLT_ROUNDSРаньше этот макрос разворачивался в константное выражение, что было неправильно, так как способ округления числа мог измениться во время выполнения программы (например, с помощью fesetround). Сейчас FLT_ROUNDS это учитывает.
and
new и deleteВ предыдущей версии библиотеки зависимые от реализации операторы new и delete экспортировались из динамической библиотеки (например msvcr120.dll). Эти операторы сейчас всегда линкуются статически с вашими двоичными файлами, даже если используются динамические библиотеки.Это не очень значительное изменение для нативного или смешанного кода (/clr), но если ваш код скомпилирован с флагом /clr: pure то после обновления код может перестать компилироваться. В этом случае нужно убедиться, что во всех нужных местах подключены заголовочные файлы или . Еще нужно учесть следующее: флаг /clr: pure объявлен устаревшим и будет удален в одном из следующих релизов.
_beginthread и _beginthreadexФункции _beginthread и _beginthreadex сейчас хранят ссылку на модуль в котором определен поток. Это нужно для того, чтобы не выгружать модуль, до тех пор пока выполняется поток.
va_start и ссылочные типыva_start теперь проводит проверку во время компиляции, не является ли переданный аргумент ссылочным типом. Если является, то, в соответствии со стандартом С++, это ошибка.
и
Все функции семейства printf и scanf теперь объявлены встроенными (inline)Определения всех функций printf и scanf перенесено объявлены inline и перенесены в , и другие заголовочные файлы CRT. Это довольно значительное изменение, которое приводит к ошибкам линковщика (LNK2019, unresolved external symbol) для всех программ, которые объявляли эти функции, без включения нужных заголовочных файлов CRT. Таким образом, при появлении этой ошибки нужно включить данные файлы, либо, если пока нет возможности (или желания) править все исходники, в качестве временного решения можно просто добавить библиотеку для линковки: legacy_stdio_definitions.libЕсли ваш проект линкуется со статическими библиотеками, которые были скомпилированы старой версией компилятора, линковщик может выдать ошибку «unresolved external symbol». Эта ошибка может быть вызвана ссылками на внутренние функции: _iob, _iob_func, или функции вида _imp_*. В этом случае мы рекомендуем перекомпилировать все статические библиотеки новой версией компилятора.Для определения всех неразрешенных символов можно воспользоваться dumpbin.exe, чтобы проверить, какие определения есть в двоичном файле, для этого нужно использовать следующую команду: dumpbin.exe /LINKERMEMBER somelibrary.lib
gets и _getwsФункции gets и _getws были удалены. gets была удалена из стандарта С11, потому что ее использование очень небезопасно. Функция _getws была просто расширением Microsoft для «широких» строк (wide strings). В качестве альтернативы можно использовать fgets, fgetws, gets_s, и _getws_s.
_cgets and _cgetwsФункции _cgets и _cgetws также были удалены. В качестве альтернативы можно использовать _cgets_s и _cgetws_s
Формат Infinity и NaNРаньше бесконечность и NaN могли были представлены с помощью специфичных для Visual C++ охранных строк (sentinel string): Infinity: 1.#INF
Quiet NaN: 1.#QNAN
Signaling NaN: 1.#SNAN
Indefinite NaN: 1.#IND
К этим значениям может быть добавлен знак.С99 представил новые требования к тому как бесконечности и NaN должны быть форматированы, сейчас Visual C++ соответствует этим требованиям. Новые строки: Infinity: inf
Quiet NaN: nan
Signaling NaN: nan (snan)
Indefinite NaN: nan (ind)
К этим значениям может быть добавлен знак.
Форматирование чисел с плавающей точкойДля увеличения точности стал применяться новый алгоритм форматирования. Эти изменения затронули функции семейства printf, scanf и функции, подобные strtod.Пример:
printf (»%.0f\n», pow (2.0, 80))
Старый вывод: 1208925819614629200000000Новый вывод: 1208925819614629174706176
Спецификаторы форматирования (format specifiers)Было улучшена точность при использовании %a и %А. Был добавлен спецификатор %F (тоже самое %f, только строки для бесконечностей и NaN выводятся заглавными буквами).Теперь спецификаторы стали проверяться на правильность. Например, раньше %hlhlhld интерпретировалась как %d, сейчас это будет ошибкой.Подобная проверка добавилась в функциях семейства fopen. Раньше эти функции могли принять неправильную строку (например: r+b+). Сейчас это также будет ошибкой.
Режим _O_U8TEXTФункция _setmode сейчас корректно сообщает о режиме открытого потока, ели он открыт в режиме _O_U8TEXT. Раньше функция возвращала ошибочную информацию о режиме _O_WTEXT.
snprintf и vsnprintfВ этом релизе были реализованы функции snprintf и vsnprintf. Раньше это были макросы.
tmpnamРаньше функции tmpnam и tmpnam_s генерировали имена файлов в корне диска (например \sd3c)Сейчас эти функции генерируют более понятные имена во временной папке.
Сокрытие реализации FILEРаньше тип FILE был полностью описан в , что делало возможным для пользователя получить доступ к внутренностям этого типа. Сейчас библиотека stdio была изменена для сокрытия деталей реализации и внутреннее строение FILE стало недоступным для пользователя.
_outp and _inpФункции _outp, _outpw, _outpd, _inp, _inpw и _inpd были удалены.
, и
strtof и wcstofРаньше эти функции не могли установить переменной errno значение ERANGE, если аргумент не мог быть представлен в виде числа типа float. Сейчас это исправлено. Следует заметить, что данная ошибка была только в указанных двух функциях, а функции strtod, wcstod, strtold, и wcstold работали так ка нужно. Нужно учесть, что данное исправление может оказать большое влияние на выполнение программы.
Функции выделения выровненной памяти (aligned allocation functions)В предыдущей версии библиотеки функции выделения выровненной памяти (_alligned_malloc, _alligned_offset_malloc) могли принять запрос на выделение блока с выравниванием, равным 0, хотя значение выравнивания должно быть степенью двойки (чем 0, конечно же не является). Сейчас при запросе выравнивания 0 байт выдается ошибка. Это изменение может повлиять на программу во время выполнения.
Функции управления «кучей» (heap functions)Функции _heapadd, _heapset и _heapused были удалены. Эти функции больше не могут выполнять свою функцию, так как CRT начал использовать кучу Windows.
smallheapФлаг линковки smallheap был удален. Более подробно: Link Options.
clockВ предыдущей версии функция clock была реализована с использованием Windows API GetSystemTimeAsFileTime, поэтому зависела от системного времени и, следовательно, не могла гарантировать монотонность. В новой реализации clock использует QueryPerformanceCounter и, благодаря этому, монотонность соблюдается.
fstat и _utimeРаньше функции _stat, fstat и _utime неправильно обрабатывали летнее время. До Visual Studio 2013 все эти функции работали используя только летнее время.В Visual Studio 2013 проблема в семействе функций _stat была исправлена, но та же самая ошибка осталась в семействах fstat и _utime. Эта ошибка была исправлена только сейчас, сейчас летнее время обрабатывается корректно и во всех функциях.
asctimeВ предыдущей версии asctime могла разбирать дату в формате с ведущими нулями, например Fri Jun 06 08:00:00 2014. Однако спецификация требует, чтобы вместо ведущих нулей использовались пробелы, т.е. Fri Jun 6 08:00:00 2014. Функция была приведена в соответствие со спецификацией.
strftime и wcsftimeФункции strftime и wcsftime теперь поддерживают следующие спецификаторы форматирования (format specifiers): %C, %D, %e, %F, %g, %G, %h, %n, %r, %R, %t, %T, %u и %V. Также парсятся и модификаторы E и O, но (пока) не используются.Спецификатор %с определяет представление даты в подходящем для текущей локали виде. Для С локали по умолчанию это формат, аналогичный %a %b %e %T %Y (такую же форму генерирует asctime). В предыдущей версии %с определял неверный формат — MM/DD/YY HH: MM: SS. Это было исправлено.
timespec и TIME_UTCЗаголовочный файл теперь определяет тип timespec и функцию timespec_get в соответствии со стандартом С11. Дополнительно определяется макрос TIME_UTC (для применения в функции timespec_get).
CLOCKS_PER_SECТеперь макрос CLOCKS_PER_SEC разворачивается в целое число типа clock_t, как этого требует стандарт языка С.
Изменения в STL
Для того, чтобы сделать возможными новые оптимизации и различные отладочные проверки, реализация С++STL в Visual Studio не ставит целью сохранение обратной совместимости на уровне двоичных файлов, поэтому объектные файлы и статические библиотеки, полученные при использовании разных версий STL, несовместимы, т.е. не могут быть скомпонованы в один двоичный файл (EXE или DLL), а объекты типов из STL не могут быть переданы между двоичными файлами, скомпилированными разными версиями компилятора. Такое смешивание двоичных файлов вызовет ошибку компоновщика про несовместимость _MSC_VER (это макрос, который содержит мажорную версию компилятора — например, 1800 для Visual Studio 2008 или раньше).Заголовочные файлы STLВ структуру включения заголовочных файлов (далее — хедеров) STL были внесены некоторые изменения. Хедеры STL могут включать друг друга в любом (неопределенном) порядке, однако в общем случае вам следует включать в свой код все хедеры, которые требуется, не полагаясь на то, что какие то хедеры находятся внутри других. Это увеличивает портируемость между версиями библиотеки и платформами. В Visual Studio 2015 RC поменялось по меньшей мере два хедера, которые могут довольно сильно повлиять на ваш код. Первый — , которые теперь не содержит . Второй — , которые объявляет std: array, не включая . И если в вашем коде есть директива «using namespace std», вы объявляете свой тип «array» и включаете (например) , то вы получите конфликт имен, так как включает и std: array будет конфликтовать с вашим array.
Аллокаторы и константностьМы сейчас требуем от оператора сравнения для аллокаторов принимать константные аргументы для обеих сторон. Если ваш аллокатор объявляет оператор сравнения так:
bool operator==(const MyAlloc& other)
то вам нужно сделать его константным:
bool operator==(const MyAlloc& other) const
Константные элементы контейнеровСтандарт С++ всегда запрещал контейнеры с константными элементами (например vector или set). Раньше Visual Studio принимала такие контейнеры, сейчас контейнер с такими элементами вызовет ошибку компиляции.
std: allocator: deallocateВ прежних версиях Visual Studio std: allocator: deallocate (p, n) игнорировала аргумент «n». Стандарт С++ требует, чтобы «n» был равен значению, переданному в качестве первого аргумента при выделении памяти для «p» с помощью std: allocator: allocate. Но тем не менее, сейчас этот аргумент проверяется, и если не соответствует значению, переданному в std: allocator: allocate, тогда программа (скорее всего) аварийно завершится.
hash_map и hash_setНестандартные заголовочные файлы hash_map и hash_set объявлены устаревшими и будут удалены в следующем релизе. Вместо них следует использовать unordered_map и unordered_set.
Компараторы и operator ()Ассоциативные контейнеры (семейство «map») сейчас требуют чтобы компараторы имели константный метод для сравнения элементов. Следующий код в классе компаратора вызовет ошибку времени компиляции:
bool operator ()(const X& a, const X& b)
метод нужно сделать константным:
bool operator ()(const X& a, const X& b) const
type traitsСтарые имена для type traits, взятые из раннего черновика стандарта С++ были заменены на новые, введенные в С++11. В следующей таблице показаны старые и соответствующие им новые имена:
Старое имя Новое имя
add_reference add_lvalue_reference
has_default_constructor is_default_constructible
has_copy_constructor is_copy_constructible
has_move_constructor is_move_constructible
has_nothrow_constructor is_nothrow_default_constructible
has_nothrow_default_constructor is_nothrow_default_constructible
has_nothrow_copy is_nothrow_copy_constructible
has_nothrow_copy_constructor is_nothrow_copy_constructible
has_nothrow_move_constructor is_nothrow_move_constructible
has_nothrow_assign is_nothrow_copy_assignable
has_nothrow_copy_assign is_nothrow_copy_assignable
has_nothrow_move_assign is_nothrow_move_assignable
has_trivial_constructor is_trivially_default_constructible
has_trivial_default_constructor is_trivially_default_constructible
has_trivial_copy is_trivially_copy_constructible
has_trivial_move_constructor is_trivially_move_constructible
has_trivial_assign is_trivially_copy_assignable
has_trivial_move_assign is_trivially_move_assignable
has_trivial_destructor is_trivially_destructible
launch: any и launch: syncНестандартные перечисления launch: any и launch: sync были убраны. Вместо launch: any нужно использовать launch: async | launch: deferred, а вместо launch: sync — launch: deferred. Более подробно можно посмотреть здесь: launch Enumeration.
Изменения в MFC и ATL
Microsoft Foundation Classes (MFC) больше не включаются в «типовую» установку Visual Studio из-за большого размера. Чтобы установить MFC, при установке нужно выбрать пользовательскую настройку и выбрать «Microsoft Foundation Classes». Если же вы уже установили Visual Studio, можно запустить процесс перестановки через панель управления.Visual C++ Redistributable Package все еще включает эту библиотеку.
© Habrahabr.ru