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

时间:2015-08-14 12:06:24

标签: c++ string boolean language-lawyer implicit-conversion

我瞪着它&试图在SO上找到类似的问题,但没有找到任何有用的东西。所以,在这里发布我的问题。

考虑这个程序:

#include <iostream>
void foo(const std::string &) {}
int main() 
{
    foo(false);
}
[Warning] converting 'false' to pointer type for argument 1 of '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.

关于此类隐式转换的标准是什么?

3 个答案:

答案 0 :(得分:8)

在C ++ 11引入nullptr关键字之前,空指针有点像黑客。任何等于零的整数文字都可以作为空指针常量,false符合条件。

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

这个问题的解决方案是使用更新的C ++方言。如有必要,将-std=c++11传递给编译器,或-std=c++14。那么你应该得到这样的东西:

error: no matching function for call to 'foo'

http://coliru.stacked-crooked.com/a/7f3048229a1d0e5a

编辑:嗯,GCC似乎还没有实施此更改。这有点令人惊讶。你可以试试Clang。

filed错误报告。

答案 1 :(得分:3)

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

  

如果s [指针]未指向Traits::length(s)+1元素的至少CharT个数组,则行为未定义。

因此出现故障(以友好例外的形式,但不依赖它)。

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

  

空指针常量是一个整数文字(2.13.2),其值为零或prvalue类型为std::nullptr_t

false的确值为零,但不是整数文字(它是一个布尔文字)。因此CharT*构造函数所采用的std::string的隐式转换是非标准的。

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

答案 2 :(得分:-1)

bool基本上是一个整数,因此它会被解释为零,在你的情况下,它可能是0字符,这将导致该问题,字符串将异常