Небольшая опечатка в моем списке инициализаций вызывает неописуемую боль
Итак, я только что закончил с изнурительным многочасовым отладочным сеансом большого серверного приложения. Ошибка сошла до едва заметной опечатки в конструкторе. В принципе, это было что-то вроде:
template <class T>
class request_handler
{
public:
request_handler(T& request, Log& error_log)
: m_request(m_request), m_error_log(error_log)
{
/*... some code ... */
}
...
};
Посмотрите на ошибку? Ну, я этого не сделал. Проблема заключается в небольшой опечатке в списке инициализаторов: m_request(m_request)
присваивает себе неинициализированную ссылку. Очевидно, он должен читать m_request(request)
.
Теперь переменная-член m_request
имеет тип T&
. Итак - есть ли причина, по которой компилятор не предупредил меня, что я использовал здесь неинициализированную переменную?
Используя GCC 4.6 с флагом -Wall
, если я скажу:
int x;
x = x;
... он выдаст предупреждение: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
Итак, почему компилятор не предупредил меня, когда я назначил m_request
себе: по существу присваивая себе неинициализированную ссылку на себя? Это избавило бы меня от досады.
Ответы
Ответ 1
Раздражающая ошибка для отслеживания. Оказывается, вам даже не нужны шаблоны для молчания на этом. Это сделает трюк:
class C {
int a, b;
public:
C(int t, int z) : a(a), b(z) { };
};
Clang предупреждает об этом с помощью -Wuninitialized
.
Хорошие новости для gcc-людей: согласно gnu bugzilla, gcc 4.7.0 исправил это.
Обновление
В gcc 4.7.0 добавьте -Wself-init
, чтобы получить это предупреждение (подтверждено sbellef):
tst.cc: В конструкторе 'C:: C (int, int): tst.cc:4:9: warning:' C:: a инициализируется с помощью [-Wuninitialized]
Ответ 2
Мне нравится использовать трюк с использованием того же имени для членов, что и параметры конструктора.
template <class T>
request_handler(T& request, Log& error_log)
: request(request), error_log(error_log)
{
/*... some code ... */
}
Это всегда предотвращает ошибку. Вы должны быть осторожны, хотя, как и в теле функции request
, относится к аргументу, а не к члену. Это, конечно, не имеет значения для простых типов, таких как ссылки, но я не рекомендую его для классов.