Здесь Будут Драконы

Просматривая материалы конференции Становимся родным, 2012 г.

(который я настоятельно рекомендую посмотреть всем программистам на C++), я обратил внимание на один пример кода:

Здесь будут драконы

  
  
  
  
  
   

#include <iostream> struct S { int n; }; struct X { X(int) {} }; void f(void*) { std::cerr << "Pointer!\n"; } void f(X) { std::cerr << "X! \n"; } int main() { f(S().

n); }

Можете ли вы, не подглядывая в ответ, сказать, что эта программа напечатает и, самое главное, Почему ? Под катом — предположение разработчика Кланг от Google о том, почему этот код работает именно так.

Еще раз для тех, кто не уловил: разработчик компилятора Google C++ не знает этого наверняка, у него есть только предположение.



Отвечать

При компиляции в соответствии со стандартом C++98 этот код выведет " ИКС! ", при компиляции в соответствии со стандартом C++11 этот код выведет " Указатель! ".



# clang++ -std=c++98 -g -o cxx11-4 cxx11-4.cpp # .

/cxx11-4 X! # clang++ -std=c++11 -g -o cxx11-4 cxx11-4.cpp # .

/cxx11-4 Pointer!



Вопрос к разработчикам стандарта C++11.



Здесь будут драконы



Пояснения

Давайте внимательно посмотрим на строку

f(S().

n);

Как видите, здесь создается экземпляр структуры S. У него нет явного конструктора, что означает вызов конструктора по умолчанию.

И здесь на сцену выходит стандарт C++11 с расширенной поддержкой константных выражений ( Обобщенные константные выражения ).

Любую функцию (включая конструктор) в C++11 можно объявить так, чтобы она всегда возвращала одно и то же выражение.

Это сделано для того, чтобы можно было писать такой код:

int get_five() {return 5;} int some_value[get_five() + 7];

Константные выражения используются в объявлениях массивов, перечислениях и блоках switch\case. И компилятор C++11 пытается считать константной любую функцию, которая может быть константой, чтобы иметь возможность использовать ее во всех этих местах.

А как насчет конструктора структуры? С ? Хорошо, если он присвоит переменной н всегда какое-то конкретное число (и стандарт этого не запрещает) — а значит, это может быть и константное выражение.

Зачем ему это назначать? н каждый раз разные значения? Присваивает ноль.

Почему именно ноль? Есть ли у вас в голове какой-нибудь более умный смысл? Итак, приведенная выше строка эквивалентна:

f(0);

Ну, это, как мы знаем, полностью эквивалентно:

f(NULL);

И это скорее превратится в пустота* чем структура X (даже с соответствующим конструктором Х(целое) ).

И теперь у нас есть явная задача недействителен f(недействителен*) ! Ну, это напечатано» Указатель! ".

Почему этого не происходит в компиляторе, поддерживающем C++98? Да, потому что в нем нет этой самой продвинутой поддержки константных выражений.

Конструктор структуры по умолчанию С нет оснований для присвоения собственности н значение равно нулю (стандарт этого не требует).

Ну, он этого не делает. Что означает линию е(S().

n); не может быть однозначно преобразовано в е(0); со всеми вытекающими последствиями.



Заключение

Стандарт C++11 новый, его поддержка в компиляторах тоже пока сырая.

Будьте готовы к таким сюрпризам.

Теги: #c++11 #C++ #драконы #C++

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.