为什么将布尔值隐式转换为字符串不是错误?

Why implicit conversion of bool to string isn't an error?

本文关键字:字符串 错误 转换 布尔值 为什么      更新时间:2023-10-16

我用google &试图在SO上找到类似的问题,但没有找到任何有用的。所以,把我的问题贴在这里。

考虑这个程序:

#include <iostream>
void foo(const std::string &) {}
int main() 
{
    foo(false);
}
<>之前[警告]将'false'转换为'std::basic_string::basic_string(const _CharT*, const _Alloc&) [with _CharT = char;_Traits = std::char_traits;_Alloc = std::allocator]' [-Wconversion-null]之前

为什么c++允许在没有显式强制转换的情况下这样做?我期待得到编译错误。由于显示以下异常,程序在运行时异常终止:

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_S_construct null not valid
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

标准对这种类型的隐式转换有什么规定?

在c++ 11引入nullptr关键字之前,空指针是一种hack。任何等于0的整数字面值都可以作为空指针常量,false符合要求。

因此,您的程序的效果是用NULLchar const *参数构造std::string。构造函数不支持空指针,因此会得到未定义的行为。

这个问题的解决方案是使用c++的一种较新的方言。如有必要,将-std=c++11-std=c++14传递给编译器。然后你应该得到这样的内容:

error: no matching function for call to 'foo'
http://coliru.stacked-crooked.com/a/7f3048229a1d0e5a

EDIT:嗯,GCC似乎还没有实现这个改变。这有点令人惊讶。你可以试试Clang。

我已经提交了一个bug报告。

实际情况是,std::string是由false隐式构造的,使用const CharT*重载并将false转换为空指针。根据该构造函数的文档:

如果s[指针]不指向至少包含CharTTraits::length(s)+1个元素的数组,则该行为是未定义的。

因此出现了故障(以友好异常的形式出现,但不要依赖它)。

现在,是正确的吗?根据[convr .ptr]:

空指针常量是一个值为0或类型为std::nullptr_t的整型字面值(2.13.2)。

false确实有一个值为0,但不是一个整数字面值(它是一个布尔字面值)。因此,std::string的构造函数所接受的到CharT*的隐式转换是非标准的。

事实上,当GCC发出警告时,Clang拒绝编译它。

bool基本上是一个整数所以它会被解释为0,在你的例子中它可能是0字符这会导致这个问题字符串会出现异常