我正在读一本关于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
}
这个函数根据书中使用字符串类的移动构造函数,通过交换字符串对象之间的指针来窃取传递给它的对象的状态(我假设它是指向第一个元素的指针,类似于内置的在数组中)而不是分别复制每个字符。
例如,假设我们有一个名为stringV
的{{1}}对象,它为3个字符串分配了足够的动态内存。我们首先分配字符串foo
,"one"
和"two"
。现在,当我们尝试推送第四个字符串"three"
时,此容器必须通过调用"four"
来重新分配内存。但是,字符串对象不是一个接一个地在相邻位置构建它们的字符(类似到内置数组的实现)。当我们使用move构造函数时,只窃取指向字符串中第一个char的指针。所以这并不意味着字符串元素(字符)reallocate
,"one"
和"two"
仍然存在于同一个旧的,现在已满的内存段中。并且新分配的内存只需要保存指向这些元素和任何新的后续字符串"three"
等的指针。被推入我们的"four"
对象?考虑到我们的字符串(字符数组)不再位于相邻位置,这对效率(至少可以说)有影响吗?
答案 0 :(得分:1)
"one"
和"two"
之类的文字确实存储在相邻的内存中,但字符串在创建到缓冲区时会复制它们(文字是只读的)。无法保证字符串分配缓冲区的位置;字符串甚至不会自己分配缓冲区,而是使用分配器。
String的移动构造函数只是将缓冲区的所有权从旧字符串传递给新字符串,它不会更改内存中缓冲区的位置,因此在reallocate
之后,所有缓冲区都将是在他们之前的相同地址。