【问题标题】:No warning for narrowing when initializing with parentheses用括号初始化时没有缩小警告
【发布时间】:2026-01-05 11:35:01
【问题描述】:

我偶然发现了一个令人困惑的情况,我发现了一个明显的缩小转换,但我很失望编译器 (gcc-4.7.2) 尽管有-Wall -Wnarrowing -pedantic 标志但没有发出警告。请看以下程序:

struct A {
  int m;
  A( int m ) : m(m) {};
};

int main() {
  unsigned long v = 0;
  A a1(v);  // narrowing, but no warning (should this not cause a warning?)
  A a2{v};  // narrowing, warning raised (expected)
}

a1 的初始化似乎在没有编译器窥视的情况下运行。为了确保我不会发疯,我尝试以相同的方式初始化a1,但使用大括号而不是括号。正如预期的那样,编译器会在第二种情况下警告缩小。

要明确:我不是在询问缩小初始化列表中的转换的合法性。我知道这是不合法的——a2 的花括号初始化只是一个健全的检查。 我的问题与初始化列表无关。这不是重复的问题。

对于a1 的初始化,编译器不应该警告我缩小范围吗?

【问题讨论】:

  • a1 的构造函数可以进行一次隐式转换,而a2 则不能。为什么你认为它们应该是一样的?
  • 如果添加-Wconversion 标志会怎样?
  • 这不是重复的。我已经知道在初始化列表中缩小转换是非法的。我问的是带括号的初始化。
  • @gx_ -Wconversion 没有任何改变。我相信-Wall 暗示了这一点
  • @IronSavior:Wall 没有暗示 Wconversion。我在 GCC 4.7 和 clang 3.3 的 Wall(以及更多的 Wconversion)中收到了警告;

标签: c++ gcc c++11 g++


【解决方案1】:

Wsign-conversion 将为该行代码生成警告 - 当 unsigned longint 具有相同大小时,-Wconversion 不会(在许多平台上都是如此,甚至在某些 64 位平台上都是如此)。对于 C 代码,-Wconversion 将隐式启用 -Wsign-conversion,但由于某些原因,C++ 不会发生这种情况。

如果您将v 的类型更改为long long-Wconversion 本身会生成警告(假设int 是32 位)。

【讨论】:

  • 非常感谢您的洞察力。我很高兴初始化器列表语义对于转换非常具体——这可能是我开始使用{} 的一个很好的理由,只要我需要代码最便携,这样编译器就可以在我实际定位之前捕获转换陷阱新平台。
最近更新 更多