我最近传递了一个指向std::string
构造函数的空指针,并得到了未定义的行为。我确信这是成千上万的程序员在我之前所做的事情,同样的错误毫无疑问地破坏了无数的程序。当使用char*
从使用std::string
的代码转换为使用std::string
的代码时会出现很多问题,并且它是在编译时无法捕获的东西,在运行时单元测试中很容易被遗漏。
我感到困惑的是以这种方式指定std::string(NULL)==""
的原因。
为什么不定义std::string(NULL)
?
效率损失可以忽略不计,我怀疑它在真实程序中是否可以衡量。
有谁知道使Traceback (most recent call last):
File "D:\Users\Martin\Desktop\copyMusic.py", line 11, in <module>
copyfile(datoteka, destination)
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\shutil.py", line 121, in copyfile
with open(dst, 'wb') as fdst:
PermissionError: [Errno 13] Permission denied: 'Desired Location To Copy The Files To'
未定义的可能原因是什么?
答案 0 :(得分:3)
唯一的原因是:运行时性能。
确定std::string(NULL)
导致空字符串确实很容易。但是,std::string
的每个const char *
的构造需要额外检查,这可能会加起来。
在绝对最大性能和便利性之间取得平衡,C ++始终追求绝对最大性能,即使这会损害程序的稳健性。
最着名的例子是默认情况下不在类中初始化POD成员变量:尽管99%的情况下程序员都希望初始化所有POD成员变量,但C ++决定不这样做以允许所有POD成员变量的1%。类可以实现稍高的运行时性能。这种模式在C ++中遍布各处。表现优于其他一切。
没有&#34;性能影响可以忽略不计&#34;在C ++中。 : - )
(请注意,我个人不喜欢C ++中的这种行为。我本来是这样做的,以便默认行为安全,并且未经检查和未初始化必须明确请求行为,例如使用额外的关键字。未初始化的变量在2018年的许多程序中仍然是一个主要问题。)
答案 1 :(得分:2)
据我所知,没有充分的理由。
有人刚提议更改此a month ago。我鼓励你支持它。
std::string
不是做得好的标准化的最好例子。最初标准化的版本无法实施;对它们的要求彼此不一致。
在某些时候,不一致是固定的。
在c++11中改变了阻止COW(写入时复制)实现的规则,这打破了现有合理兼容std::string
的ABI。这种变化可能是解决不一致的问题,我不记得了。
它的API与std
容器的其余部分不同,因为它不是来自同一个前std
STL。
将std::string
的这种遗留行为视为考虑性能成本的某种合理决策是不现实的。如果进行了任何此类测试,那就是20多年前的非标准合规std::string
(因为没有一个可以存在,标准不一致)。
由于惯性,它在传递(char const*)0
和nullptr
时仍然是UB,并且会继续这样做,直到有人提出提案并证明费用很小虽然好处不是。
从文字std::string
构建char const[N]
已经是一种低性能解决方案;你已经在编译时获得了字符串的大小,然后将它放在地面上,然后在运行时遍历缓冲区以找到'\0'
字符(除非进行优化;如果是这样,则null检查同样可以优化) 。高性能解决方案包括了解长度并告知std::string
,而不是从'\0'
终止缓冲区复制。