【问题标题】:How to avoid clang-tidy warnings about uninitialized variables如何避免关于未初始化变量的整洁警告
【发布时间】:2021-10-02 04:20:56
【问题描述】:

我正在寻找使用clang-tidy 避免cppcoreguidelines-init-variables 警告的最佳方法。

std::istringstream in(line);
float x, y, z, rotx, roty, rotz;
in >> x >> y >> z >> rotx >> roty >> rotz;

-> 变量“x”未初始化,变量“y”未初始化,...

double min_intensity, max_intensity;    
cv::Point point_min, point_max;
cv::minMaxLoc(input, &min_intensity, &max_intensity, &point_min, &point_max, elliptic_mask_around_center);

-> 变量 'min_intensity' 未初始化,...

我可以为xy、...、min_intensitymax_intensity 指定一个值,但我不明白为什么要这样做。

避免此警告的最佳方法是什么?

float x = 0.F; // initialize to a value, but 6 lines, and it makes no sense because x is never 0
float x = NAN; // works but 6 lines, and needs <cmath> inclusion
float x, y, z, rotx, roty, rotz; // NOLINT [not very practical, and means the warning is a false positive]

感谢您的帮助。

【问题讨论】:

  • 当来自流的输入失败时,变量将具有不确定的值,稍后在代码中使用它们将调用未定义的行为。你最好初始化它们
  • 实际检查 IO 操作是否成功,而不是一味地假设它成功了并继续前进,如果一切顺利也不会受到伤害。
  • @463035818_is_not_a_number 检查读取是否有效在这里是必不可少的,因为即使您使用任意值初始化它们,如果读取失败,它也是一个等待发生的错误。
  • @463035818_is_not_a_number:自at least C++11 以来,情况并非如此。
  • @DavisHerring 是和否。如果x 提取失败,则流处于错误状态,后续提取不会初始化其他变量

标签: c++ clang-tidy


【解决方案1】:

一般而言,您应该始终初始化变量,因为从未初始化的变量中读取是未定义的行为。

当从流中提取失败时,从 C++11 开始分配 0。但是,只有当流不处于失败状态时才会出现这种情况。因此,当读取 x 失败时,x 的值将是 0,但其他的值将是不确定的。

您应该经常检查提取是否成功:

if (in >> x >> y >> z >> rotx >> roty >> rotz) { 
     // use x,y,z,rotx,roty,rotz
}

如果你想使用部分输入,即使在某些时候提取失败,你应该单独阅读它们:

if (in >> x) {
     // use x
}
if (in >> y) {
     // use y
}
// ...

如果你这样做,初始化严格来说是没有必要的。但是,从流中读取比初始化变量要昂贵得多,因此为了保持一致(参见例如here),我建议无论如何都要初始化它们。不要担心更多的代码行,一个常见的建议是无论如何每行声明一个变量(参见例如here):

std::istringstream in(line);
float x = 0.0;
float y = 0.0;
float rotx = 0.0;
float roty = 0.0;
float rotz = 0.0;
if (in >> x >> y >> z >> rotx >> roty >> rotz) {
     // extraction succeeded
} else {
     // extraction failed
}

【讨论】:

  • 非常感谢您的回答。这可能是异端,但我为什么要关心这是未定义的行为,只要程序不崩溃?如果提取失败,我不会使用 x, y, z,所以我不介意它们的值可能用 (0, NAN, -1, 325.824, ... - NAN 似乎是一个更合理的选择方式)。
  • @PJ127 因为除非您研究程序集,否则您不知道程序在具有未定义行为时会做什么。它不一定会崩溃,但它可能会做一些完全出乎意料的事情而不会崩溃。当您使用不同的编译器标志、不同的编译器或第二天的相同编译器再次编译程序时,您无法保证程序仍然执行它所做的工作。事实是,有很多程序具有未定义的行为并且它们确实有效,直到它们没有。始终初始化变量是避免讨厌的错误的一种简单方法,那么为什么不这样做呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-24
  • 2021-12-06
  • 2016-08-12
相关资源
最近更新 更多