Недавно читали код и наткнулись на примерно такой такой фрагмент.
bool *t = new bool[X][Y];
// много строк
switch (t[M][N])
{
case true:
// много строк
break;
case false:
// много строк
break;
default:
// много строк
break;
}
Сразу возникает вопрос: зачем нужна ветка default? Если переменная не равна true, то она равна false. Однокурсник сказал: «Для отладки». Думаю: что тут можно отлаживать? Но не всё так просто.
Запускаю. Выполняется код в ветке default. Самое первое предположение — забыли поставить break. Внимательно перечитываю код — всё в порядке. Запускаю в отладчике и замечаю, что выполняется сразу ветка default, а в ветку true или false даже не заходит. Решаю просмотреть значение переменной. Visual Studio 2012 запущенная на Windows 7 показывает 205. Допустим. Плюсы я стал учить недавно, поэтому решил провести небольшой опыт: создал булевую переменную и присвоил ей 205. Отрабатывает ветка true. Пока я размышлял над этой проблемой, однокурсник нашёл решение этой проблемы: оказывается, массив не был инициализирован. После инициализации проблема исчезла. Теперь у меня возник возник вопрос: неужели проблема в switch? Ради проверки я решил провести следующий опыт.
#include <iostream>
using namespace std;
int main() {
bool *t = new bool[1];
switch (t[0])
{
case true:
cout << "truen";
break;
case false:
cout << "falsen";
break;
default:
cout << "superpositionn";
break;
}
if(t[0] == true) {
cout << "truen";
} else if(t[0] == false) {
cout << "falsen";
} else {
cout << "superpositionn";
}
if(t[0]) {
cout << "truen";
} else if(!t[0]) {
cout << "falsen";
} else {
cout << "superpositionn";
}
delete[] t;
return 0;
}
Вариант с switch или первый вариант с if позволяет определить не инициализированную булевую переменную. Второй вариант с if никогда не заходит в третий вариант.
Как создать такую переменную Шрёдингера? Создайте динамический или статический массив. Используйте его перед инициализацией. А также, самое вкусное, то, что вы можете скопировать это неопределённое значение, даже в скалярную переменную. Где это может пригодится — решать вам.
Интересно также то, что если перед проверкой вставить:
char a = t[0];
t[0] = a;
то переменная наконец-то станет true. А если написать
bool a = t[0];
t[0] = a;
то ничего не изменится.
Позднее я повторил опыт на Visual Studio 2013 с 5 пакетом обновления запущенная на Windows 7. Там отладчик говорит, что неинициализированная переменная равна true, но несмотря на это в блок true не заходит. Также она говорит, что ветка default не нужна, так как все возможные метки уже заданы. Но несмотря на это заходит в блок default.
В Linux данная особенность не проявляется.
Автор: alsoijw