C++11 обратная совместимость (преобразование нулевой целочисленной константы в указатель)

стандарт C++ позволяет неявное преобразование нуля целочисленную константу к указателю любого типа.

следующий код недопустим, так как значение v не является постоянным здесь:

float* foo()
{
    int v = 0;
    return v;    // Error
}

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

float* foo()
{
    const int v = 0;
    return v;    // Ok in C++98 mode, error in C++11 mode
}

вопрос почему gcc и clang (пробовал разные версии) скомпилируйте код правильно в режиме c++98/03, но верните предупреждение/ошибку при компиляции в режиме c++11/14 (-std=c++11)? Я попытался найти изменения в рабочем проекте PDF на C++11, но безуспешно.

компиляторы Intel compiler 16.0 и VS2015 не показывают ошибок и предупреждений в обоих случаях.

1 ответов


GCC и Clang ведут себя по-разному с -std=c++11 поскольку C++11 изменил определение константы нулевого указателя, а затем C++14 изменил его снова, см. Core д-р 903, который изменил правила в C++14, так что только литералы null указатель константы.

в C++03 4.10 [conv.ПТР] сказал:

константа нулевого указателя-это интегральное выражение константы (5.19) rvalue целочисленного типа, которое вычисляется как ноль.

что позволяет всевозможные выражения, пока они постоянны и оцениваются до нуля. Перечисления,false, (5 - 5) etc. так далее. ... это вызывало множество проблем в коде C++03.

в C++11 говорится:

константа нулевого указателя-это интегральное выражение константы (5.19) prvalue целочисленного типа, которое вычисляется как ноль или prvalue типа std::nullptr_t.

и в C++14 он говорит:

константа нулевого указателя-это целочисленный литерал (2.14.2) со значением zero или prvalue типа std::nullptr_t.

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