禁用本地变量的未初始化警告

时间:2014-05-26 14:16:31

标签: c++ compiler-errors initialization compiler-warnings

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

  1. 我不允许更改编译器标志
  2. 解决方案必须适用于所有编译器(即,没有gnu扩展或其他编译器特定属性)
  3. 我想仅在特定的局部变量上使用它。其他未初始化的本地人仍应触发警告
  4. 解决方案不应生成任何说明。
  5. 我无法改变局部变量的类。即,我不能简单地添加一个"什么都不做"构造
  6. 当然,最简单的解决方案是初始化变量。但是,变量的类型初始化成本很高(即使默认初始化成本很高),并且代码在非常热的循环中使用,所以我不想浪费CPU周期来保证被覆盖的初始化无论如何,在阅读之前。

    那么是否存在一种独立于平台,与编译器无关的方式告诉编译器本地变量不需要初始化?

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

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

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

2 个答案:

答案 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);
  }
}