Eva*_*ran 7 c++ optimization standard-library proxy-object
我只是想着实施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_;
};
Run Code Online (Sandbox Code Playgroud)
这个类的公共接口将模仿真实的所有只读操作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;
}
Run Code Online (Sandbox Code Playgroud)
std::string总共不会构造2个对象.对于执行大量字符串操作的代码来说,这似乎是一种有用的优化.当然,这不仅适用于std::string任何可以返回其内容子集的类型.
据我所知,没有实现这样做.
我想问题的核心是:
给定一个可以根据需要隐式转换为类的类std::string,是否符合库编写者的标准,将成员的原型更改为返回类型?或者更一般地说,库编写者是否有余地在这些类型的情况下作为优化返回"代理对象"而不是常规对象?
我的直觉是,这是不允许的,原型必须完全匹配.鉴于您不能单独重载返回类型,这将使图书馆编写者无法利用这些类型的情况.就像我说的,我认为答案是否定的,但我想我会问:-).
这个想法是写时复制,但不是COW整个缓冲区,而是跟踪缓冲区的哪个子集是"真正的"字符串.(COW,正常形式,在某些库实现中使用(是?).)
所以你根本不需要代理对象或更改界面,因为这些细节可以完全在内部完成.从概念上讲,您需要跟踪四件事:源缓冲区,缓冲区的引用计数以及此缓冲区中字符串的开始和结束.
无论何时操作根本修改缓冲区,它都会创建自己的副本(从开始和结束分隔符开始),将旧缓冲区的引用计数减1,并将新缓冲区的引用计数设置为1.其余的引用计数规则是相同的:复制并将计数增加1,破坏字符串并将计数减1,达到零并删除等.
substr 只创建一个新的字符串实例,除了明确指定了开始和结束分隔符.