我想在动态数组中从用户那里获取一个简单的字符串数组。例如,如果我将数组1000的大小。如何删除数组中未使用的空间,使其仅适合用户输入的大小而不删除整个数组?
答案 0 :(得分:1)
内存分配器通常不允许释放已分配内存的部分内容,并且C ++中指定的分配工具当然不提供此类功能的任何接口。
有一个标准函数'realloc',它可以允许分配的内存块显然被扩展。然而,这通常的工作方式是底层分配器检查以前分配的内存块是否已经足够大。也就是说,当您分配1000个字节时,分配器可能会提供大于而不是1000个字节的内存块。
隐藏的“额外”内存对于访问是有效的,就像你要求它一样,但是由于你没有要求它而且不知道有多少,如果有的话,额外的内存是存在的,你是有限的只访问你实际请求的字节。
realloc
将为您提供新大小的已分配内存,其内容与您传递给它的参数所指向的内存相同。它可以通过发现现有的内存块足够大于所请求的新大小来做到这一点,在这种情况下,它只返回传递给它的相同指针。在这种情况下,您知道有额外的内存,现在您可以访问所需的大小。
如果“额外”内存不足,或者realloc
实现很简单,那么realloc
将分配一个新块,将数据复制到新块中,释放旧块,以及返回新指针。
减少数组的内存量几乎总是意味着分配一个新的,更小的数组,将内容复制到新数组中,然后释放旧的更大的数组。例如vector::shrink_to_fit
和旧的'swap with empty'技巧可以做到这一点。
如果你想避免分配太多的内存,那么你应该首先避免分配过多的内存。你应该只是分配正确的金额来开始。
如果这种方法意味着您不会参与不良做法,例如,分配一些您认为比您需要的更大的固定大小的数组:
#include <iostream>
#include <string>
int main() {
std::string user_input[10000]; // should be enough for anyone
int count = 0;
for (std::string s; std::cin >> s;) {
user_input[count] = s;
++count;
}
magic_array_size_reducing_function(user_input, count);
}
上面的代码是错误的,因为用户可能会超出固定限制并导致程序中断。事实上,只要你看到这样的固定限制,你就应该怀疑,并且代码可能需要修复。你也应该怀疑任何要求你这样做的开始编程书或课程。
写这个的正确方法是没有固定限制,而是根据需要动态增加资源使用。
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<std::string user_input;
for (std::string s; std::cin >> s;) {
user_input.push_back(s);
}
//...
}
手动执行此操作只是意味着根据需要进行分配/复制/释放舞蹈。下面是一个我只实现最低限度的例子。
#include <iostream>
#include <string>
struct dynamic_string_array {
int capacity, size;
std::string *user_input;
dynamic_string_array() {
capacity = 0;
size = 0;
user_input = nullptr;
}
~dynamic_string_array() {
delete [] user_input;
}
void push_back(std::string const &s) {
if (size == capacity) {
int new_capacity = capacity ? 16 : capacity * 1.5;
std::string *new_user_input = new std::string[new_capacity];
for (int i = 0; i < size; ++i) {
new_user_input[i] = user_input[i];
}
// ---
delete [] user_input;
user_input = new_user_input;
capacity = new_capacity;
}
user_input[size] = s;
++size;
}
};
int main() {
dynamic_string_array user_input;
for (std::string s; std::cin >> s;) {
user_input.push_back(s);
}
//...
}