我瞪着它&试图在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.
关于此类隐式转换的标准是什么?
答案 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字符,这将导致该问题,字符串将异常