看看这个例子(取自here):
class foo {
std::string my_str_;
public:
std::string_view get_str() const {
return my_str_.substr(1u);
}
};
这段代码很糟糕,因为 substr
返回一个临时的 std::string
,所以返回的 std::string_view
引用了一个已经被破坏的对象 . 但是,如果 substr
返回 std::string_view
,则此问题不存在 .
此外,如果 substr
返回 std::string_view
而不是 std::string
,对我来说似乎合乎逻辑,因为返回的字符串是字符串的视图,并且它更高效,因为没有复制 .
如果 substr
返回 std::string_view
会有任何缺点(除了明显的缺点:失去与C 14的一些兼容性 - 我知道是否存在其他缺点)?
相关问题:How to efficiently get a string_view
for a substring of std::string
4 回答
当
string_view
被发明时,关于它是否应该存在的争论太多了 . 所有相反的论点都来自你所展示的例子 .但是,就像我总是告诉每个人这样糟糕的例子:C不是Java,也不是Python . C是一种低级语言,你几乎可以完全控制记忆,我重复蜘蛛侠的陈词滥调:强大的力量带来了巨大的责任感 . 如果您不知道
string_view
是什么,那就不要使用它!问题的另一部分有一个简单的答案,你自己回答:
危害在于,使用
substr
中字符串副本的每个程序可能都不再有效 . 向后兼容性在计算机业务中是一件严肃的事情,这就是为什么英特尔's 64-bit processors still accept x86 instructions, which is also why they'没有停业 . 重新发明轮子要花很多钱,金钱是编程的重要组成部分 . 所以,除非你计划将所有C扔进垃圾箱并重新开始(比如RUST),否则你应该在每个新版本中保留旧规则 .你可以弃用东西,但要非常小心和非常慢 . 但是,弃用与改变API不同,这正是您所建议的 .
缺点是非常清楚:对于每个版本的C回到开头,这将是一次重大的API破坏性变化 .
C不是一种倾向于破坏API兼容性的语言 .
这是一个当前安全的具体(如果稍微不完整)代码示例,但随着更改将成为未定义的行为:
可以说
auto
的使用在这里有点可疑,但在以下情况下完全合理(在我看来),重复类型名称几乎是多余的:编辑:即使
substr()
总是返回std::string_view
,你可以想象这段代码会造成一些痛苦,即使只是在开发/调试期间 .首先,c字符串的基础数据结构主要与c字符串保持兼容(可通过
c_str()
成员访问) . C字符串null
终止 . 所以你基本上只有一个起始char
指针,并保持增量,直到指针指向0
.因此,子字符串可以从原始字符串的任意位置开始 . 但是,由于您不能在原始字符串中的某处插入
null
,因此您的子字符串仍然需要与原始字符串在同一位置结束 .--edit--正如John Zwinck所指出的,c字符串可以包含
\0
个字符,但是这仍然意味着子字符串会松散它们的c_str
成员,因为它需要修改原始字符串 . Using std::string_view with api, what expects null terminated string的一个缺点也被注意到Using std::string_view with api, what expects null terminated string