所以,我刚刚完成了一个大型服务器应用程序的艰苦的多小时调试会话。错误最终归结为构造函数中几乎没有明显的错字。基本上,它是这样的:
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
时没有警告我:基本上是为自己分配了一个未初始化的引用?这本来可以节省我几个小时的烦恼。
答案 0 :(得分:11)
令人讨厌的bug追踪。事实证明,你甚至不需要模板来静默地失败。这就行了:
class C {
int a, b;
public:
C(int t, int z) : a(a), b(z) { };
};
Clang用-Wuninitialized
警告这个。
gcc人们的好消息:根据gnu的bugzilla,gcc 4.7.0 has fixed this。
<强>更新强>
在gcc 4.7.0上,添加-Wself-init
以获取此警告(由sbellef验证):
tst.cc:在构造函数'C :: C(int,int)'中:tst.cc:4:9:警告:'C :: a'用自己初始化[-Wuninitialized]
答案 1 :(得分:3)
我喜欢使用成员使用相同名称作为构造函数参数的技巧。
template <class T>
request_handler(T& request, Log& error_log)
: request(request), error_log(error_log)
{
/*... some code ... */
}
这将始终防止错误。你必须要小心,因为在函数体request
中引用的是参数,而不是成员。这当然对于简单类型(如引用)无关紧要,但我不建议将它用于类。