Rug*_*rra 13 c++ string casting boolean
有没有理由在c ++ std::string中没有隐式转换为bool?例如
std::string s = ""
if (s) { /* s in not empty */ }
Run Code Online (Sandbox Code Playgroud)
和其他语言一样(例如python).我认为使用这种empty方法很繁琐.
Jer*_*fin 24
现在C++ 11已经添加了显式转换和上下文转换的概念,这可能会被添加.
什么std::string时候设计,但这些都不存在.这使得支持转换的类bool很难保持安全.特别是,这种转换可能(并且会发生)在许多你几乎从未想过的情况下发生.例如,如果我们假设std::string转换为falseif而不是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
}
Run Code Online (Sandbox Code Playgroud)
上下文转换稍微增加了一点,让转换为bool隐式发生,但只是在if语句中,所以使用上面的转换函数的类,你会得到:
X x;
if (x) // allowed
int y = x; // would require explicit cast to compile
Run Code Online (Sandbox Code Playgroud)
我补充一点,关于"正交性"的抱怨在这里似乎很不适用.虽然方便,但将字符串转换为布尔值并不是很有意义.如果有的话,我们应该抱怨string("0")转换到1(在发生这种情况的语言中)有多奇怪.
本文提到了一些operator bool()可能导致令人惊讶的结果的原因.
请注意,这std::string只是一个typedef std::basic_string<char>.还有std::wstring多字节字符.隐式转换可以让你写:
std::string foo = "foo";
std::wstring bar = "bar";
if (foo == bar) {
std::cout << "This will be printed, because both are true!\n";
}
Run Code Online (Sandbox Code Playgroud)
std::string 仍然必须与 C 风格的字符串共存。
根据定义,C 样式字符串是“由第一个空字符终止并包括第一个空字符的连续字符序列”,通常通过指向其第一个字符的指针进行访问。"hello, world"在大多数情况下,诸如此类的表达式会隐式转换为指向第一个字符的指针。然后可以将这样的指针隐式转换为bool,true如果指针为非空,false则为空。(在 C 中,它没有转换为bool,但它仍然可以直接用作条件,因此效果几乎相同。)
所以,由于 C++ 的 C 遗产,如果你写:
if ("") { ... }
Run Code Online (Sandbox Code Playgroud)
空字符串已被视为true,并且在不破坏 C 兼容性的情况下无法轻易更改。
我建议使用 C 风格的空字符串评估 astrue和 C++ 空std::string评估 asfalse会太混乱。
写作if (!s.empty())是不是那个困难的(恕我直言这是更清晰)。