【问题标题】:How does the string move constructor work?字符串移动构造函数是如何工作的?
【发布时间】:2015-02-08 09:26:41
【问题描述】:

我正在阅读一本关于 c++ 的书,试图学习这门语言。 有一个示例,它创建了一个类向量类,该类仅适用于名为stringV 的字符串。该类定义了一个名为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

}

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

【问题讨论】:

    标签: c++ string memory dynamic move


    【解决方案1】:

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

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

    【讨论】:

    • 你的意思是它们存储在相邻的位置,如 [o][n][e][null][t][w][o][null],还是 mem_reigon[o][n ][e][null] diffrent_reigon [t][w][o][null]
    • 它们在程序二进制文件的同一部分中,最终将位于同一内存区域,因此彼此接近。无法保证它们是 [o][n][e][null][t][w][o][null] 还是 [o][n][e][null][other literal][其他文字][t][w][o][null].
    • 所以从某种意义上说,当我在 stringV 对象中分配动态内存时,我为指向字符串的指针而不是实际的字符分配内存
    • 您正在为string 的实例分配内存。这些实例包含指向它们的缓冲区(字符所在的位置)的指针,这些缓冲区位于内存中的其他位置。它们还包含其他数据,例如分配器的实例以及缓冲区的大小和容量。
    猜你喜欢
    • 1970-01-01
    • 2018-09-23
    • 2011-03-08
    • 2018-06-26
    • 2012-05-09
    • 2011-01-26
    • 1970-01-01
    • 2021-12-23
    • 2012-03-13
    相关资源
    最近更新 更多