C++ std::strings 的 capacity()、reserve() 和 resize() 函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9521629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
std::strings's capacity(), reserve() & resize() functions
提问by zar
I wan to use std::string simply to create a dynamic buffer and than iterate through it using an index. Is resize() the only function to actually allocate the buffer?
我想使用 std::string 来创建一个动态缓冲区,然后使用索引对其进行迭代。resize() 是实际分配缓冲区的唯一函数吗?
I tried reserve() but when I try to access the string via index it asserts. Also when the string's default capacity seems to be 15 bytes (in my case) but if I still can't access it as my_string[1]
.
我试过 Reserve() 但是当我尝试通过索引访问字符串时,它会断言。此外,当字符串的默认容量似乎是 15 个字节(在我的情况下)但如果我仍然无法以my_string[1]
.
So the capacity of the string is not the actual buffer? Also reserve() also does't allocate the actual buffer?
那么字符串的容量不是实际的缓冲区?还保留()也不分配实际缓冲区?
string my_string;
// I want my string to have 20 bytes long buffer
my_string.reserve( 20 );
int i = 0;
for ( parsing_something_else_loop )
{
char ch = <business_logic>;
// store the character in
my_string[i++] = ch; // this crashes
}
If I do resize() instead of reserve() than it works fine. How is it that the string has the capacity but can't really access it with []? Isn't that the point to reserve() size so you can access it?
如果我做 resize() 而不是 reserve() ,它工作正常。字符串有容量但不能真正用[]访问它是怎么回事?这不是保留()大小以便您可以访问它的要点吗?
Add-onIn response to the answers, I would like to ask stl folks, Why would anybody use reserve() when resize() does exactly the same and it also initialize the string? I have to say I don't appreciate the performance argument in this case that much. All that resize() does additional to what reserve() does is that it merely initialize the buffer which we know is always nice to do anyways. Can we vote reserve() off the island?
附加组件 作为对答案的回应,我想问 stl 人,当 resize() 完全相同并且它还初始化字符串时,为什么有人会使用 Reserve()?我不得不说我不太欣赏这种情况下的性能论点。除了reserve() 所做的之外,resize() 所做的只是初始化缓冲区,我们知道无论如何这样做总是很好的。我们可以在岛外投票吗?
回答by kennytm
Isn't that the point to reserve() size so you can access it?
这不是保留()大小以便您可以访问它的要点吗?
No, that's the point of resize()
.
不,这就是重点resize()
。
reserve()
only gives to enough room so that future call that leads to increase of the size (e.g. calling push_back()
) will be more efficient.
reserve()
只提供足够的空间,以便将来导致大小增加的调用(例如调用push_back()
)将更有效率。
From your use case it looks like you should use .push_back()
instead.
从您的用例看来,您应该.push_back()
改用。
my_string.reserve( 20 );
for ( parsing_something_else_loop )
{
char ch = <business_logic>;
my_string.push_back(ch);
}
How is it that the string has the capacity but can't really access it with []?
字符串有容量但不能真正用[]访问它是怎么回事?
Calling .reserve()
is like blowing up mountains to give you some free land. The amount of free land is the .capacity()
. The land is there but that doesn't mean you can live there. You have to build houses in order to move in. The number of houses is the .size()
(= .length()
).
打电话.reserve()
就像炸山给你一些免费的土地。自由土地的数量是.capacity()
。土地在那里,但这并不意味着你可以住在那里。你必须盖房子才能搬进来。房子的数量是.size()
(= .length()
)。
Suppose you are building a city, but after building the 50th you found that there is not enough land, so you need to found another place large enough to fit the 51st house, and then migrate the whole population there. This is extremely inefficient. If you knew you need to build 1000 houses up-front, then you can call
假设你正在建造一座城市,但在建造了第 50 座之后,你发现没有足够的土地,所以你需要另找一个足够容纳 51 座房子的地方,然后将所有人口迁移到那里。这是非常低效的。如果您知道需要预先建造 1000 座房屋,那么您可以致电
my_string.reserve(1000);
to get enough land to build 1000 houses, and then you call
获得足够的土地来建造 1000 所房子,然后你打电话
my_string.push_back(ch);
to construct the house with the assignment of ch
to this location. The capacity is 1000, but the size is still 1. You may not say
建造房子,分配ch
到这个位置。容量是1000,但大小还是1。你可能不会说
my_string[16] = 'c';
because the house #16 does not exist yet. You may call
因为房子 #16 还不存在。你可以打电话
my_string.resize(20);
to get houses #0 ~ #19 built in one go, which is why
一口气建好房子#0 ~ #19,这就是为什么
my_string[i++] = ch;
works fine (as long as 0 ≤ i≤ 19).
工作正常(只要 0 ≤ i≤ 19)。
See also http://en.wikipedia.org/wiki/Dynamic_array.
另见http://en.wikipedia.org/wiki/Dynamic_array。
For your add-on question,
对于您的附加问题,
.resize()
cannot completely replace .reserve()
, because (1) you don't always need to use up all allocated spaces, and (2) default construction + copy assignment is a two-step process, which could take more time than constructing directly (esp. for large objects), i.e.
.resize()
不能完全替换.reserve()
,因为 (1) 你并不总是需要用完所有分配的空间,并且 (2) 默认构造 + 复制赋值是一个两步过程,这可能比直接构造花费更多的时间(特别是对于大型对象),即
#include <vector>
#include <unistd.h>
struct SlowObject
{
SlowObject() { sleep(1); }
SlowObject(const SlowObject& other) { sleep(1); }
SlowObject& operator=(const SlowObject& other) { sleep(1); return *this; }
};
int main()
{
std::vector<SlowObject> my_vector;
my_vector.resize(3);
for (int i = 0; i < 3; ++ i)
my_vector[i] = SlowObject();
return 0;
}
Will waste you at least 9 seconds to run, while
会浪费你至少 9 秒的运行时间,而
int main()
{
std::vector<SlowObject> my_vector;
my_vector.reserve(3);
for (int i = 0; i < 3; ++ i)
my_vector.push_back(SlowObject());
return 0;
}
wastes only 6 seconds.
仅浪费6秒。
std::string
only copies std::vector
's interface here.
std::string
std::vector
这里只复制的界面。
回答by Jerry Coffin
No -- the point of reserve
is to prevent re-allocation. resize
sets the usable size, reserve
does not -- it just sets an amount of space that's reserved, but not yet directly usable.
不——重点reserve
是防止重新分配。resize
设置可用大小,reserve
不 - 它只是设置保留的空间量,但尚未直接可用。
Here's one example -- we're going to create a 1000-character random string:
这是一个例子——我们将创建一个 1000 个字符的随机字符串:
static const int size = 1000;
std::string x;
x.reserve(size);
for (int i=0; i<size; i++)
x.push_back((char)rand());
reserve
is primarilyan optimization tool though -- most code that works with reserve
should also work (just, possibly, a little more slowly) without calling reserve
. The one exception to that is that reserve
can ensure that iterators remain valid, when they wouldn't without the call to reserve.
reserve
不过,它主要是一个优化工具——大多数可以使用的代码也reserve
应该在不调用reserve
. 一个例外是reserve
可以确保迭代器保持有效,而如果没有调用 Reserve 的话。
回答by dasblinkenlight
The capacity
isthe length of the actual buffer, but that buffer is privateto the string; in other words, it is not yours to access. The std::string
of the standard library mayallocate more memory than is required to storing the actual characters of the string. The capacity is the total allocated length. However, accessing characters outside s.begin()
and s.end()
is still illegal.
的capacity
是实际的缓冲区的长度,但该缓冲器是私有的字符串; 换句话说,访问不是你的。的std::string
标准库的可分配比需要存储该字符串的实际字符更多的内存。容量是分配的总长度。然而,外界访问字符s.begin()
和s.end()
仍然是非法的。
You call reserve
in cases when you anticipate resizing of the string to avoid unnecessary re-allocations. For example, if you are planning to concatenate ten 20-character strings in a loop, it may make sense to reserve 201 characters (an extra one is for the zero terminator) for your string, rather than expanding it several times from its default size.
reserve
当您预计调整字符串大小以避免不必要的重新分配时,您可以调用。例如,如果您计划在循环中连接 10 个 20 个字符的字符串,则为您的字符串保留 201 个字符(一个额外的字符用于零终止符)可能是有意义的,而不是将其从默认大小扩展数次.
回答by Christian Rau
reserve(n)
indeed allocates enough storage to hold at least n
elements, but it doesn't actually fill the container with any elements. The string is still empty (has size 0), but you are guaranteed, that you can add (e.g. through push_back
or insert
) at least n
elements before the string's internal buffer needs to be reallocated, whereas resize(n)
really resizes the string to contain n
elements (and deletes or adds new elements if neccessary).
reserve(n)
确实分配了足够的存储空间来容纳至少n
元素,但它实际上并没有用任何元素填充容器。字符串仍然是空的(大小为 0),但您可以保证,在需要重新分配字符串的内部缓冲区之前,您可以添加(例如,通过push_back
或insert
)至少n
元素,而resize(n)
真正调整字符串的大小以包含n
元素(并删除或如果需要,添加新元素)。
So reserve
is actually a mere optimization facility, when you know you are adding a bunch of elements to the container (e.g. in a push_back
loop) and don't want it to reallocate the storage too often, which incurs memory allocation and copying costs. But it doesn't change the outside/client view of the string. It still stays empty (or keeps its current element count).
所以reserve
实际上只是一个优化工具,当您知道要向容器添加一堆元素(例如在push_back
循环中)并且不希望它过于频繁地重新分配存储时,这会导致内存分配和复制成本。但它不会改变字符串的外部/客户端视图。它仍然保持为空(或保持其当前元素计数)。
Likewise capacity
returns the number of elements the string can hold until it needs to reallocate its internal storage, whereas size
(and for string also length
) returns the actual number of elements in the string.
同样capacity
返回字符串在需要重新分配其内部存储之前可以保存的元素数,而size
(对于 string 也是length
)返回字符串中的实际元素数。
回答by Branko Dimitrijevic
Just because reserve
allocates additional space does not mean it is legitimate for you to access it.
仅仅因为reserve
分配了额外的空间并不意味着您可以合法地访问它。
In your example, either use resize
, or rewrite it to something like this:
在您的示例中,要么使用resize
,要么将其重写为如下所示:
string my_string;
// I want my string to have 20 bytes long buffer
my_string.reserve( 20 );
int i = 0;
for ( parsing_something_else_loop )
{
char ch = <business_logic>;
// store the character in
my_string += ch;
}
回答by J?rg Beyer
std::vectorinstead of std::stringmight also be a solution - if there are no requirements against it.
std::vector而不是std::string也可能是一个解决方案 - 如果没有针对它的要求。
vector<char> v; // empty vector
vector<char> v(10); // vector with space for 10 elements, here char's
your example:
你的例子:
vector<char> my_string(20);
int i=0;
for ( parsing_something_else_loop )
{
char ch = <business_logic>;
my_string[i++] = ch;
}