为什么c++ 23 string::resize_and_overwrite调用操作作为右值?



为了提高向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

    -kbemin(o, n).

    -pcharT*,使得[p,p + n]范围有效,this->compare(0, k, p, k) == 0true。中的值范围[p + k,p + n]可能是不确定的[basic.indet]。

    -OP为表达式std::move(op)(p, n)

    -r = OP.

  • […]

    1. Effects:计算OP,将*this的内容替换为[p,p + r),并使所有指向[p,p + n]范围的指针和引用无效。

    但是我发现这个函数在调用它之前会使用std::moveop转换为右值,这意味着我们不能传入一个只有左值重载的可调用对象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——它正在"过期"。因为它在调用后立即被销毁。如果你特别设计了只支持左值调用的可调用对象,那么库很乐意阻止这种情况的发生。