为什么 std::string 不接受空指针?

Why doesn't std::string take a null pointer?

我最近将空指针传递给 std::string 构造函数并得到未定义的行为。我敢肯定这是在我之前成千上万的程序员做过的事情,同样的错误无疑使无数程序崩溃。从使用 char* 的代码转换为使用 std::string 的代码时,它会出现很多,而且它是那种在编译时无法捕获的东西,很容易在 运行 时间单位中被遗漏测试。

让我感到困惑的是为什么要这样指定 std::string

为什么不直接定义 std::string(NULL)==""

效率损失可以忽略不计,我怀疑它在实际程序中是否可以测量。

有谁知道 std::string(NULL) 未定义的可能原因是什么?

据我所知没有充分的理由。

有人刚刚提议对此进行更改 a month ago。我鼓励你支持它。

std::string 并不是标准化工作做得很好的最好例子。最初标准化的版本无法实施;对它的要求彼此不一致。

在某些时候,不一致已得到修复。

中更改的规则阻止了 COW(写时复制)实现,这破坏了现有合理兼容的 std::string 的 ABI。此更改可能是解决不一致的地方,我不记得了。

它的 API 不同于 std 容器的其余部分,因为它不是来自同一个 std 之前的 STL。

std::string 的这种遗留行为视为某种考虑到性能成本的合理决策是不现实的。如果进行过任何此类测试,那是 20 多年前在符合 non-standard 的 std::string 上进行的(因为 none 可能存在,标准不一致)。

由于惰性,它在通过(char const*)0nullptr时仍然是UB,并且会继续这样做,直到有人提出建议并进行演示成本很小,而收益却很小。

从文字 char const[N] 构造 std::string 已经是一个低性能的解决方案;您在编译时已经有了字符串的大小,然后将其放在地上,然后在运行时遍历缓冲区以找到 '[=20=]' 字符(除非对其进行了优化;如果是这样,空检查同样可以优化) .高性能解决方案涉及了解长度并告诉 std::string 它而不是从 '[=20=]' 终止缓冲区复制。

唯一的原因是:运行时性能。

确实很容易定义 std::string(NULL) 结果为空字符串。但是在从 const char * 构造每个 std::string 时需要额外检查,这可以加起来。

在绝对最大性能和便利性之间取得平衡,C++ 总是追求绝对最大性能,即使这意味着会损害程序的健壮性。

最著名的例子是默认不初始化 类 中的 POD 成员变量:即使在 99% 的情况下,程序员都希望初始化所有 POD 成员变量,但 C++ 决定不这样做以允许所有 类 的 1% 获得稍高的运行时性能。这种模式在 C++ 中无处不在。性能高于一切。

C++中没有"the performance impact would be negligible"。 :-)

(请注意,我个人也不喜欢 C++ 中的这种行为。我本来可以让 default 行为 safe],并且必须显式请求未检查和未初始化的行为,例如使用额外的关键字。未初始化的变量在 2018 年仍然是许多程序中的主要问题。)