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

时间:2017-09-04 10:47:56

标签: c++ string c++17

看一下这个例子(取自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 个答案:

答案 0 :(得分:2)

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

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

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

  

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

使用来自substr的字符串副本的每个程序都可能不再有效。向后兼容性在计算机业务中是一件严肃的事情,这就是为什么英特尔的64位处理器仍然接受x86指令,这也是他们没有停业的原因。重新发明轮子要花很多钱,金钱是编程的重要组成部分。所以,除非你打算把所有的C ++都扔进垃圾箱并重新开始(比如RUST),你应该在每个新版本中维护旧的规则。

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

答案 1 :(得分:1)

缺点很明显:与每个版本的C ++重新开始相比,这将是一次重大的API破坏变化。

C ++不是一种容易破坏API兼容性的语言。

答案 2 :(得分: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,您也可以想象这段代码会造成一些痛苦,即使只是在开发/调试过程中。

答案 3 :(得分:0)

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

中也注意到string_view的缺点