首页 文章

如果std :: string :: substr返回std :: string_view会有什么缺点?

提问于
浏览
3

看看这个例子(取自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 回答

  • 2

    string_view 被发明时,关于它是否应该存在的争论太多了 . 所有相反的论点都来自你所展示的例子 .

    但是,就像我总是告诉每个人这样糟糕的例子:C不是Java,也不是Python . C是一种低级语言,你几乎可以完全控制记忆,我重复蜘蛛侠的陈词滥调:强大的力量带来了巨大的责任感 . 如果您不知道 string_view 是什么,那就不要使用它!

    问题的另一部分有一个简单的答案,你自己回答:

    如果substr返回std :: string_view会有任何缺点(除了明显的缺点:失去与C 14的一些兼容性)?

    危害在于,使用 substr 中字符串副本的每个程序可能都不再有效 . 向后兼容性在计算机业务中是一件严肃的事情,这就是为什么英特尔's 64-bit processors still accept x86 instructions, which is also why they'没有停业 . 重新发明轮子要花很多钱,金钱是编程的重要组成部分 . 所以,除非你计划将所有C扔进垃圾箱并重新开始(比如RUST),否则你应该在每个新版本中保留旧规则 .

    你可以弃用东西,但要非常小心和非常慢 . 但是,弃用与改变API不同,这正是您所建议的 .

  • 0

    缺点是非常清楚:对于每个版本的C回到开头,这将是一次重大的API破坏性变化 .

    C不是一种倾向于破坏API兼容性的语言 .

  • 1

    这是一个当前安全的具体(如果稍微不完整)代码示例,但随着更改将成为未定义的行为:

    std::string some_fn();
    auto my_substr = some_fn().substr(3, 4);
    

    可以说 auto 的使用在这里有点可疑,但在以下情况下完全合理(在我看来),重复类型名称几乎是多余的:

    const char* some_fn();
    auto my_substr = std::string(some_fn()).substr(3, 4);
    

    编辑:即使 substr() 总是返回 std::string_view ,你可以想象这段代码会造成一些痛苦,即使只是在开发/调试期间 .

  • 1

    首先,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

相关问题