字符串移动构造函数如何工作?

How does the string move constructor work?

我正在阅读一本关于 C++ 的书以尝试学习这门语言。 有一个例子,它创建了一个类似向量的 class,它只适用于名为 stringV 的字符串。 class 定义了一个名为 reallocate 的函数,该函数应分配新的动态内存并将其字符串移动到新内存,以防旧内存已满。

void stringV::reallocate(){
    size_t newcap = size() ? size() * 2 : 1;
    auto newalloc = alloc.allocate(newcap); 
    auto mem = newalloc;
    auto elem = element; // element pointes to the first string object in the memory segment
    for (size_t i = 0; i < size(); i++){
        alloc.construct(newalloc, std::move(*elem));
        newalloc++;
        elem++;
    }
    free(); //destroys and deallocates the dynamic memory held by this object
    element = mem;
    first_free = newalloc; // one past the last element
    cap = element + newcap; // last part of the possibly unconstructed memory

}

根据书本,此函数使用字符串 class 的移动构造函数 ,通过在字符串对象之间交换指针(我假设是指向第一个元素的指针,类似于内置数组)而不是单独复制每个字符。 例如,假设我们有一个名为 foostringV 对象,它已为 3 个字符串分配了足够的动态内存。我们首先分配字符串 "one""two""three"。现在当我们尝试压入第四个字符串 "four" 时,这个容器将不得不通过调用 reallocate 重新分配内存 但是,字符串对象不是一个接一个地在相邻位置构造它们的字符吗(类似到内置数组的实现)。当我们使用移动构造函数时,我们只是窃取了指向字符串中第一个字符的指针。所以这是否意味着字符串元素(字符) "one""two""three" 仍然在同一个旧的、现在已满的内存段中。并且新分配的内存只需要保存指向这些元素的指针和任何新的后续字符串,"four"...等。被推入我们的 foo 对象?考虑到我们的字符串(char 数组)不再位于相邻位置,这不会对效率产生影响(至少可以说)吗?

"one""two" 这样的文字确实存储在相邻的内存中,但字符串在创建到缓冲区时会复制它们(文字是只读的)。无法保证字符串将在何处分配缓冲区;字符串甚至不自己分配缓冲区,而是使用分配器。

String 的移动构造函数只是将缓冲区的所有权从旧字符串传递给新字符串,它不会更改缓冲区在内存中的位置,因此在 reallocate 之后,所有缓冲区都将位于他们之前的地址相同。