在C++中,为什么std::string
不能隐式转换为布尔值?例如:
std::string s = ""
if (s) { /* s in not empty */ }
就像其他编程语言(例如Python)一样,我认为使用empty
方法很繁琐。
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
的情况是多么奇怪。
这篇文章提到了一些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";
}
std::string
仍需与C风格字符串共存。
C风格字符串的定义是“以及包括第一个空字符的连续字符序列”,通常通过指向其第一个字符的指针进行访问。例如"hello, world"
,在大多数情况下,会隐式转换为指向第一个字符的指针。然后可以将这样的指针隐式转换为bool
,如果指针非空,则得到true
,否则得到false
。(在C中,它不会被转换为bool
,但仍然可以直接用作条件,因此效果几乎相同。)
因此,由于C++的C遗产,如果您写:
if ("") { ... }
空字符串已被视为true
,要改变这一点会破坏C兼容性,因此很难进行修改。
我建议将C风格的空字符串评估为true
,而将C++空std::string
评估为false
,这样做太令人困惑了。
写if (!s.empty())
并不是那么困难(我认为更可读)。
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)
的方法,请告诉我们。
bool()
操作符,那么它应该如何定义?你认为为空为假,非空为真的原因是什么? - deviantfan