有没有理由说c ++ std::string
没有隐式转换为bool?例如
std::string s = ""
if (s) { /* s in not empty */ }
和其他语言一样(例如python)。我认为使用empty
方法很繁琐。
答案 0 :(得分:22)
在C ++ 11添加了显式转换和上下文转换的概念之后,可能会添加 。
设计std::string
时,这些都不存在。这使得支持转换为bool
的类很难保持安全。特别是,这种转换可能(并且会发生)在许多你几乎从未想过的情况下发生。例如,如果我们假设std::string
转换为false
,如果为空,则转换为true
,那么您可以使用string
本质上任何地方整数或者是指针。
编译器不会告诉你类型不匹配,而是将字符串转换为bool,然后将bool转换为整数(false - > 0,true - > 1)。
这样的事情经常发生,很多早期的字符串类型尝试(并且有很多),委员会显然认为最好将隐式转换保持在绝对最小值(所以仅限于此string
支持的隐式转换是从C风格的字符串创建一个字符串对象。)
为了更安全地处理转换为bool,设计了许多方法。一个是转换为void *
,这可以防止一些问题,但不会转换为其他问题(iostreams会使用它)。还有一个“安全的bool”成语(实际上,更像是一个“安全的bool”主题,其中有几个变体)。虽然这些肯定会改进对转换将允许和不允许的转换的控制,但是大多数转换涉及相当大的开销(典型的安全bool需要大约50行代码的基类,以及来自该基类的派生等。 )
关于显式转换和上下文转换如何提供帮助,基本思路非常简单。您可以(从C ++ 11开始)将转换函数标记为explicit
,这允许仅在使用显式强制转换为目标类型的情况下使用它:
struct X {
explicit operator bool() { return true; }
};
int main() {
X x;
bool b1 = static_cast<bool>(x); // compiles
bool b2 = x; // won't compile
}
上下文转换会稍微增加一点,让转换为bool隐式发生,但仅类似于if
语句,所以使用带有上述转换函数的类,你会得到:
X x;
if (x) // allowed
int y = x; // would require explicit cast to compile
我补充一点,关于“正交性”的抱怨在这里似乎很不适用。虽然方便,但将字符串转换为布尔值并不是很有意义。如果有的话,我们应该抱怨string("0")
转换为1
(在发生这种情况的语言中)有多奇怪。
答案 1 :(得分:9)
This article提到了operator bool()
可能导致令人惊讶的结果的一些原因。
请注意,std::string
只是std::basic_string<char>
的typedef。对于多字节字符,还有std::wstring
。隐式转换可以让你写:
std::string foo = "foo";
std::wstring bar = "bar";
if (foo == bar) {
std::cout << "This will be printed, because both are true!\n";
}
答案 2 :(得分:4)
std::string
仍然必须与C风格的字符串共存。
C样式字符串按照定义&#34;由第一个空字符&#34;终止并包含第一个空字符&#34;的连续字符序列,通常通过指向其第一个字符的指针访问。在大多数情况下,诸如"hello, world"
之类的表达式被隐式转换为指向第一个字符的指针。然后可以将这样的指针隐式转换为bool
,如果指针为非空,则产生true
,如果指针为空,则产生false
。 (在C中,它没有转换为bool
,但它仍然可以直接用作条件,因此效果几乎相同。)
所以,由于C ++的C传承,如果你写:
if ("") { ... }
空字符串已被视为true
,并且在不破坏C兼容性的情况下无法轻松更改。
我建议将C风格的空字符串评估为true
,将C ++空std::string
评估为false
会让人感到困惑。
写if (!s.empty())
答案 3 :(得分:2)
我能找到的与你(和我)想要的最接近的是以下内容。
您可以在!
上定义std::string's
运算符,如下所示:
bool operator!(const std::string& s)
{
return s.empty();
}
这允许你这样做:
std::string s;
if (!s) // if |s| is empty
使用简单的否定,你可以做到:
if (!!s) // if |s| is not empty
这有点尴尬,但问题是,你想要避免多余角色多么糟糕? !strcmp(...)
也很尴尬,但我们仍然运作并习惯了它,我们很多人更喜欢它,因为它比输入strcmp(...) == 0
更快。
如果有人在C ++中发现了if (s)
的方法,请告诉我们。