为了提高向std::string
写入数据的性能,c++ 23专门为std::string
引入了resize_and_overwrite()
。在字符串。容量],标准描述如下:
template<class Operation> constexpr void resize_and_overwrite(size_type n, Operation op);
让
-
o = size()
,然后再调用resize_and_overwrite
。-
k
bemin(o, n)
.-
p
为charT*
,使得[p
,p + n
]范围有效,this->compare(0, k, p, k) == 0
为true
。中的值范围[p + k
,p + n
]可能是不确定的[basic.indet]。-
OP
为表达式std::move(op)(p, n)
。-
r = OP
.[…]
- Effects:计算
OP
,将*this
的内容替换为[p
,p + r
),并使所有指向[p
,p + n
]范围的指针和引用无效。
但是我发现这个函数在调用它之前会使用std::move
将op
转换为右值,这意味着我们不能传入一个只有左值重载的可调用对象operator()
(demo):
#include <string>
int main() {
struct Op {
int operator()(char*, int) &;
int operator()(char*, int) && = delete;
} op;
std::string s;
s.resize_and_overwrite(42, op); // ill-formed
}
这个行为看起来有点奇怪,但是由于这个改变是在最后一版的论文,显然是有意为之。
那么,这背后的考虑是什么呢?在op
必须作为右值调用的任务中是否有任何好处?
op
在被销毁之前只被调用一次,因此将其作为右值调用允许任何&&
重载它以重用它可能持有的任何资源。
可调用对象在道德上是一个xvalue——它正在"过期"。因为它在调用后立即被销毁。如果你特别设计了只支持左值调用的可调用对象,那么库很乐意阻止这种情况的发生。