本文介绍了std::strings 的容量()、reserve() &调整大小()函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只想使用 std::string 来创建动态缓冲区,然后使用索引对其进行迭代.resize() 是唯一真正分配缓冲区的函数吗?

我尝试了 Reserve() 但是当我尝试通过索引访问字符串时,它会断言.此外,当字符串的默认容量似乎是 15 个字节(在我的情况下)但如果我仍然无法以 my_string[1] 访问它.

所以字符串的容量不是实际的缓冲区?Reserve() 也不分配实际的缓冲区?

string my_string;//我希望我的字符串有 20 字节长的缓冲区my_string.reserve(20);int i = 0;for ( parsing_something_else_loop ){char ch = <business_logic>;//将字符存入my_string[i++] = ch;//这会崩溃}

如果我使用 resize() 而不是 reserve() 则它工作正常.字符串有容量但不能真正用[]访问它是怎么回事?这不是保留() 大小以便您可以访问它的要点吗?

插件针对这些答案,我想问 stl 的人,当 resize() 完全相同并且它还初始化字符串时,为什么有人会使用 Reserve()?我不得不说我不太欣赏这种情况下的性能论点.除了reserve() 所做的之外,resize() 所做的只是初始化缓冲区,我们知道无论如何这样做总是很好的.我们可以在岛上投票给 Reserve() 吗?

解决方案

不,这就是 resize() 的重点.

reserve() 只提供足够的空间,以便将来导致大小增加的调用(例如调用 push_back())将更有效.

从您的用例看来,您应该改用 .push_back().

my_string.reserve( 20 );for ( parsing_something_else_loop ){char ch = <business_logic>;my_string.push_back(ch);}

字符串有容量但不能真正用[]访问是怎么回事?

调用 .reserve() 就像炸山给你一些免费的土地.空闲土地的数量是.capacity().土地在那里,但这并不意味着你可以住在那里.你必须盖房子才能搬进来.房子的数量是.size() (= .length()).

假设你正在建造一座城市,但在建造了第 50 座之后,你发现没有足够的土地,所以你需要另找一个足够容纳 51 座房子的地方,然后将所有人口迁移到那里.这是非常低效的.如果您知道需要预先建造 1000 所房屋,那么您可以致电

my_string.reserve(1000);

获得足够的土地来建造 1000 所房子,然后你打电话

my_string.push_back(ch);

使用 ch 分配到这个位置来建造房子.容量是1000,但大小还是1.你可能不会说

my_string[16] = 'c';

因为房子 #16 还不存在.你可以打电话

my_string.resize(20);

一次性建造房屋#0 ~ #19,这就是为什么

my_string[i++] = ch;

工作正常(只要 0 ≤ i ≤ 19).

另见http://en.wikipedia.org/wiki/Dynamic_array.>

对于您的附加问题,

.resize() 不能完全替代 .reserve(),因为 (1) 你并不总是需要用完所有分配的空间,以及 (2)默认构造+复制赋值是一个两步过程,这可能比直接构造花费更多的时间(特别是对于大对象),即

#include #include 结构慢对象{慢对象(){ 睡眠(1);}SlowObject(const SlowObject& other) { sleep(1);}慢对象&运算符=(const SlowObject& other){ sleep(1);返回 *this;}};int main(){std::vectormy_vector;my_vector.resize(3);for (int i = 0; i 

会浪费你至少 9 秒的时间来运行,而

int main(){std::vectormy_vector;my_vector.reserve(3);for (int i = 0; i 

只浪费了 6 秒.

std::string 这里只复制了 std::vector 的接口.

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?

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].

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?

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?

解决方案

No, that's the point of 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.

From your use case it looks like you should use .push_back() instead.

my_string.reserve( 20 );

for ( parsing_something_else_loop )
{
    char ch = <business_logic>;
    my_string.push_back(ch);
}


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()).

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

my_string.reserve(1000);

to get enough land to build 1000 houses, and then you call

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

my_string[16] = 'c';

because the house #16 does not exist yet. You may call

my_string.resize(20);

to get houses #0 ~ #19 built in one go, which is why

my_string[i++] = ch;

works fine (as long as 0 ≤ i ≤ 19).

See also 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.

#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

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.

std::string only copies std::vector's interface here.

这篇关于std::strings 的容量()、reserve() &amp;调整大小()函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-25 08:04