为了提高写入数据的性能std::string
,C++23专门引入resize_and_overwrite()
了std::string
. 在[字符串.容量]中中,标准描述如下:
\n\nRun Code Online (Sandbox Code Playgroud)\ntemplate<class Operation>\nconstexpr void resize_and_overwrite(size_type n, Operation op);\n
\n
\n- \n
让
\n\xe2\x80\x94
\no = size()
在调用之前resize_and_overwrite
。\xe2\x80\x94
\nk
是min(o, n)
。\xe2\x80\x94
\np
是 acharT*
,使得范围 [p
,p + n
] 有效并且this->compare(0, k, p, k) == 0
在true
调用之前。p + k
[ , ]范围内的值p + n
可能是不确定的[basic.indet]。\xe2\x80\x94
\nOP
是表达式std::move(op)(p, n)
。\xe2\x80\x94
\nr = OP
。[...]
\n\n
\n- 效果:计算,用 [ , )
\nOP
替换 的内容,并使 [ , ]范围内的所有指针和引用无效。*this
p
p + r
p
p + n
但我发现这个函数在调用它之前将用于std::move
转换op
为右值,这意味着我们不能传入仅重载左值的可调用对象operator()
(demo):
#include <string>\n\nint main() {\n struct Op {\n int operator()(char*, int) &;\n int operator()(char*, int) && = delete;\n } op;\n std::string s;\n s.resize_and_overwrite(42, op); // ill-formed\n}\n
Run Code Online (Sandbox Code Playgroud)\n这种行为似乎有点奇怪,但由于此更改是在上一版本中进行的\n论文的
\n那么,这背后有哪些考虑呢?op
必须作为右值调用的任务有什么好处吗?
T.C*_*.C. 11
op
在被销毁之前只调用一次,因此将其作为右值调用允许&&
对其进行任何重载以重用它可能持有的任何资源。
可调用对象在道德上是一个 xvalue - 它是“过期”的,因为它在调用后立即被销毁。如果您专门设计了可调用对象以仅支持作为左值调用,那么库很乐意阻止其工作。