禁用局部变量的未初始化警告

Disable uninitialized warning for a local variable

本文关键字:初始化 警告 局部变量      更新时间:2023-10-16

当局部变量第一次使用时未初始化时,c++编译器会发出警告。然而,有时,我知道变量总是在使用之前被写入,所以我不需要初始化它。当然,当我这样做时,编译器会发出警告。由于我的团队正在使用-Werror进行构建,因此代码无法编译。如何为特定的局部变量关闭此警告?我有以下限制:

  1. 我不允许改变编译器标志
  2. 解决方案必须在所有编译器上工作(即,没有gnu扩展或其他编译器特定的属性)
  3. 我只想在特定的局部变量上使用这个。其他未初始化的局部变量仍应触发警告
  4. 解决方案不应生成任何指令。
  5. 我不能修改局部变量的类。例如,我不能简单地添加一个"什么都不做"的构造函数。
当然,最简单的解决方案是初始化变量。然而,该变量的类型初始化成本很高(即使默认初始化成本也很高),并且该代码用于非常热的循环,因此我不想浪费CPU周期来进行初始化,因为无论如何在读取之前都保证会被覆盖。 那么,有没有一种平台无关的、编译器无关的方式来告诉编译器局部变量不需要初始化?

下面是一些可能触发此类警告的示例代码:

void foo(){
    T t;
    for(int i = 0; i < 100; i++){
       if (i == 0) t = ...;
       if (i == 1) doSomethingWith(t);
    }
}

如您所见,第一个循环初始化t,第二个循环使用它,因此t永远不会在未初始化的情况下被读取。然而,编译器无法推断出这一点,因此它发出警告。注意,为了简洁起见,这段代码非常简化。

我的回答将推荐另一种方法:而不是禁用警告代码,只是在实现上做一些重新制定。我看到了两种方法:

第一选择

可以使用指针而不是真正的对象,并保证在需要时将其初始化,例如:

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永远不会是基本类型(int、float等)。因此,您可以使用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);
}

如果代码不是很复杂,我通常展开其中一个迭代:

void foo(){
  T t;
  t = ...;
  for(int i = 1; i < 100; i++){
    doSomethingWith(t);
  }
}