【问题标题】:Why does a compiler allow a user to change the type of an 'auto' variable?为什么编译器允许用户更改“自动”变量的类型?
【发布时间】:2021-12-29 11:11:32
【问题描述】:

我希望 auto 关键字能够从初始化程序中推断出变量的类型一次,并在整个代码中保持该类型。令我惊讶的是,我的编译器 (g++ 9.3.0) 允许我更改它的类型,它仍然可以工作。当我首先将变量用作 int 然后用作浮点数时,这对我来说是可以接受的。但是当我使用auto 关键字声明一个字符串,然后为该变量分配一个浮点值时,编译器不会抛出错误,也不会在浮点赋值后打印该值。有人可以解释为什么它首先允许将浮点值分配给字符串变量吗?编译器是否每次都接受新的赋值?还是它会引发某种我无法捕捉的异常?下面的代码 -

#include <iostream>

int main()
{
 auto x = '2';
 
 std::cout << x << std::endl;
 
 x = 3.0; // Why is this allowed?
 
 std::cout << x << std::endl; // This won't print
 
 return 0;
}

【问题讨论】:

  • 它将进行从 double 到 char 的缩小转换(它不会改变 x 的类型)。第二行将打印一个 3 字符(不是 '3'),这是一个不可见的字符,但它确实可以打印换行符。 auto 可能看起来像一个“神奇”的东西,但实际上它的定义非常好。
  • 现在试试x = 65.0
  • c/c++ 编译器的问题在于他们认为我们知道自己在做什么;) -- 士气:始终启用所有警告。
  • “隐式转换是一个错误”一书中的另一页。
  • auto 与您所看到的无关。试试char x = '2';,它定义x的方式与auto相同,你会看到同样的东西。

标签: c++ g++ auto


【解决方案1】:

为了向您展示发生了什么,我通过一些编译时类型检查扩展了示例:

#include <type_traits>
#include <iostream>

int main()
{
    auto x = '2';

    // decltype(x) is the type for variable x
    // compare it at compile time with char type
    static_assert(std::is_same_v<decltype(x), char>);

    std::cout << x << std::endl;

    x = 3.0; // Why is this allowed? because it does a narrowing conversion from double to char
    // my compiler even gives this warning :
    // main.cpp(11,6): warning C4244: '=': conversion from 'double' to 'char', possible loss of data
    
    // type of x is still the same and it is still a char
    static_assert(std::is_same_v<decltype(x), char>);

    std::cout << static_cast<int>(x) << std::endl; // the cast is here to be able to print the actual value of the char

    return 0;
}

【讨论】:

  • 这真的很有帮助,谢谢!顺便说一句,您使用的是什么编译器?我使用 -Wall 开关尝试了与 g++ 9.3.0 相同的代码,但没有显示任何警告。
  • 不客气,我正在使用 mscv。事实上,即使将 -Wconversion 添加到 gcc (godbolt.org/z/qrxnchhar) 也不会触发 gcc 的此警告(奇怪)。
【解决方案2】:

但是当我使用 auto 关键字声明一个字符串时

你很困惑。这段代码声明了一个char类型的变量:

auto x = '2';

如果你确实想声明一个字符串,你必须使用双引号:

auto x = "2";

3.0 的后续分配将不会随着此更改而编译。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-21
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-08
    • 2015-05-29
    • 2011-08-15
    相关资源
    最近更新 更多