当首次使用时本地变量未初始化时,C ++编译器会发出警告。但是,有时,我知道变量将在使用之前始终被写入,因此我不需要初始化它。当我这样做时,编译器会发出警告。由于我的团队正在使用-Werror
构建,因此代码将无法编译。如何为特定的局部变量关闭此警告。我有以下限制:
当然,最简单的解决方案是初始化变量。但是,变量的类型初始化成本很高(即使默认初始化成本很高),并且代码在非常热的循环中使用,所以我不想浪费CPU周期来保证被覆盖的初始化无论如何,在阅读之前。
那么是否存在一种独立于平台,与编译器无关的方式告诉编译器本地变量不需要初始化?
以下是一些可能触发此类警告的示例代码:
void foo(){
T t;
for(int i = 0; i < 100; i++){
if (i == 0) t = ...;
if (i == 1) doSomethingWith(t);
}
}
如您所见,第一个循环周期初始化t而第二个循环使用它,因此t永远不会被未初始化读取。但是,编译器无法推断出这一点,因此它会发出警告。请注意,为简洁起见,此代码非常简化。
答案 0 :(得分:1)
我的回答将推荐另一种方法:不要禁用警告代码,只需对实现进行一些重新设计。我看到两种方法:
第一个选项
您可以使用指针而不是真实对象,并保证在您需要时将其初始化,例如:
std::unique_ptr<T> t;
for(int i=0; i<100; i++)
{
if(i == 0) if(t.empty()) t = std::unique_ptr<T>(new T); *t = ...;
if(i == 1) if(t.empty()) t = std::unique_ptr<T>(new T); doSomethingWith(*t);
}
值得注意的是,可能在i==0
时,您不需要使用默认构造函数构建t
。我无法猜测你的operator=
是如何实现的,但我想说你可能正在分配一个已经在...
段中省略的代码中分配的对象。
第二个选项
由于您的代码经历了如此巨大的性能损失,我可以推断T永远不会是一个基本的tipe(整数,浮点数等)。因此,您可以使用init方法重新实现类T,而不是使用指针,并避免在构造函数上初始化它。您可以使用一些布尔值来指示类是否需要初始化:
class FooClass()
{
public:
FooClass() : initialized(false){ ... }
//Class implementation
void init()
{
//Do your heavy initialization code here.
initialized = true;
}
bool initialized() const { return initialized; }
private:
bool initialized;
}
你可以这样写:
T t;
for(int i=0; i<100; i++)
{
if(i == 0) if(!t.initialized()) t.init(); t = ...;
if(i == 1) if(!t.initialized()) t.init(); doSomethingWith(t);
}
答案 1 :(得分:0)
如果代码不是很复杂,我通常会展开其中一个迭代:
void foo(){
T t;
t = ...;
for(int i = 1; i < 100; i++){
doSomethingWith(t);
}
}