如何在语言级别将变量标记为已初始化?

How to mark a variable as initialized at the language level?

我正在使用链接的 C 库将值放入变量中。

void f_wrapper(int& v){
   auto s = f_legacy(&v);
   if(s != success) throw std::runtime_error{};
}

...

  int value;  // clang-tidy complains here: using "variable 'value' is not initialized"
  f_wrapper(value);

然而,clang-tidy 在这里抱怨:使用“变量 'value' 未初始化”。

据了解,这仅仅是因为编译器无法看穿链接函数。

我不想做 int value = 0(因为我相信库会初始化 value 并且我相信“部分形成”的值。) 另外,我希望不要添加 // NOLINT(warning) 只是为了抑制警告。 (该模式经常重复。)

有什么我可以用语言将value标记为已初始化吗?

我正在寻找类似的东西:

void f_wrapper(int& v) {
   auto s = f_legacy(&v);
   if(s != success) throw std::runtime_error{};
   [[mark initialized(v)]];
}

最坏的情况我可以在包装器内部做到这一点,因为至少我没有看到主代码中不必要的初始化,但是在数组是初始化。我也不想为此初始化付出代价或选择默认值。

void f_wrapper(int& v) {
   v = int{};  // initialize to suppress warning at high level code
   auto s = f_legacy(&v);
   if(s != success) throw std::runtime_error{};
}

这不是您想听到的,但实际上只有 一种 方法可以在标准 C++ 中“在语言级别”初始化变量——那就是 初始化它。这真的很简单。正如您在问题中已经描述的那样,您基本上要么坚持这个,要么 NOLINTing 它。这不是一个迷人的解决方案,也不是您所追求的;但真的没有更好的办法了。

我确信可能有一些方法可以“欺骗”工具,使其认为它已初始化,但任何此类建议充其量只是黑客攻击。

也就是说;假设导致悲伤的 clang-tidy 检查是 cppcoreguidelines-init-variables 规则,值得注意的是这个 触发整数、布尔值、浮点数、双精度数和指针 - 和默认初始化这样一个值的成本通常可以忽略不计。除非您已对该成本进行基准测试并发现默认初始化这是一个 真正的瓶颈 ,否则几乎没有理由避免这种做法。

一般来说,初始化变量是解决这个问题最干净/最安全的方法,最终也是最佳实践无论如何。没有初始化,只需要 small f_legacy 中的错误即可导致意外的 UB。如果 f_legacy 有任何错误使得它 return 成功但忘记将值设置为 v,那么 v 将不会被初始化并且将正式成为 UB -- 并且这只是为了保存默认初始化原语。


只是一个建议:

根据您的“最坏情况”f_wrapper 示例,NOLINT调用调用者或必须初始化其他人的未初始化值,API 是否可以更改到 return 初始化值而不是初始化传入的内容?

如果您这样做,您可以在内部 NOLINT 它,因此需要的 NOLINT 更少,或者您自己初始化该值以防止其他潜在问题。由于该值被封装在函数中,因此这比初始化调用者的可能未初始化的值要简单得多,在我看来:

int f_wrapper() {
   auto v = int{};
   auto s = f_legacy(&v);
   if(s != success) throw std::runtime_error{};

   return v;
}