我在思考std::string::substr
的实现。它返回一个新的std::string
对象,这似乎有些浪费。为什么不返回一个引用原始字符串内容的对象,可以隐式地赋值给std::string
?一种对实际复制进行惰性评估的类。这样的类可能看起来像这样:
template <class Ch, class Tr, class A>
class string_ref {
public:
// not important yet, but *looks* like basic_string's for the most part
private:
const basic_string<Ch, Tr, A> &s_;
const size_type pos_;
const size_type len_;
};
这个类的公共接口应该模仿真正的
std::string
的所有只读操作,所以使用起来是无缝的。 std::string
可以有一个新的构造函数,它接受一个string_ref
,这样用户就不会知道。当您尝试“存储”结果时,您最终将创建一个副本,因此引用指向数据然后在其背后进行修改没有真正的问题。这个想法是像这样的代码:
std::string s1 = "hello world";
std::string s2 = "world";
if(s1.substr(6) == s2) {
std::cout << "match!" << std::endl;
}
希望不要有超过2个std::string
对象被构造出来,这对于执行大量字符串操作的代码来说似乎是一种有用的优化。当然,并不仅适用于std::string
,而是适用于可以返回其子集的任何类型。
据我所知,没有实现这种优化的。
我想问题的核心是:
如果一个类可以隐式转换为std::string
,那么库编写者改变成员函数的原型返回类型是否符合标准?或者更一般地说,在这些情况下,库编写者是否有余地返回“代理对象”而不是常规对象以进行优化?
我的直觉是不允许这样做,原型必须完全匹配。考虑到你不能仅仅因为返回类型不同而重载,这将不留余地给库编写者利用这些情况的空间。像我说的,我认为答案是不行的,但我想问一下:-)。
llvm::StringRef
这样的吗? - Matthieu M.operator[]
、at
),这实际上需要提前复制,即使它不会有用。 - Matthieu M.