开发者

C++ string uses maximum buffer allocated?

I declare a variable string s;

and do s = "abc"; now it has buffer of 3 characters.

After

s = "abcd" it has a buffer of 4 characters.

Now after the third 开发者_StackOverflow社区statement

s = "ab" question is will it keep the buffer of 4 characters or will it reallocate a 2 character buffer?

If it will allocate 2 character buffer is there any way I can tell it to keep the allocated maximum buffer.

So does it keep the buffer of maximum size ever allocated ?

s = "ab"
s="abc"
s="a"
s="abcd"
s="b"

Now it should keep a buffer of size 4.

Is that possible?


The string will keep its buffer once it is allocated, and only reallocate if its needs an even larger buffer. It will also likely start with an initial buffer size larger than 3 or 4.

You can check the allocated size using the capacity() member function.


After James' comments below I still believe my answer is correct for the examples given in the question.

However, for a reference counted implementation a sequence like this

s = "some rather long string...";

std::string t = "b";
s = t;

would set s.capacity() to be equal to t.capacity() if the implementation decides to share the internal buffer between s and t.


s = "ab" question is will it keep buffer of 4 words or will it reallocate 2 word buffer ?

It will not reallocate the buffer. I don't know if it's mentioned in the standard, but all the implementations I have ever seen issue a reallocation only if they need to increase the capacity. Never to decrease. Even if you have a string with 4 characters and call .resize(2) or .reserve(2) the capacity will not change. In order to force the string (or containers) to reallocate memory to fit the exact size, there's a simple swap trick for that

s.swap(string(s));

What happens here? You create a temporary from s which will have its capacity exactly equal to s.size() then swap it with your original string. The destructor of the temporary will free all the necessary resources.

Again, I am not claiming this is standard, but all the implementations I've seen have this behavior.


You can easily see the behavior of your implementation by calling std::string::capacity at various times. In general, I'd be surprised if any implementation ever had a buffer of three characters. (Not words, but bytes, at least on most modern machines.) In practice, implementations vary, and also vary depending on how the new length comes about: with g++, for example, removing characters with std::string::erase will not reduce the capacity of the string, but assigning a new, smaller string will. VC++ doesn't reduce the capacity in either case. (In general, VC++ and g++ have very different strategies with regards to memory management in strings.)

EDIT:

Given the other responses (which don't even correspond to usual practice): here's the small test program I used to verify my statements above (although I really didn't need it for g++—I know the internals of the implementation quite well):

#include <string>
#include <iostream>
#include <iomanip>

template<typename Traits>
void
test()
{
    std::string s;
    size_t lastSeen = -1;
    std::cout << Traits::name() << ": Ascending:" << std::endl;
    while ( s.size() < 150 ) {
        if ( s.capacity() != lastSeen ) {
            std::cout << "  " << std::setw( 3 ) << s.size()
                << ": " << std::setw( 3 ) << s.capacity() << std::endl;
            lastSeen = s.capacity();
        }
        Traits::grow( s );
    }
    std::cout << Traits::name() << ": Descending: " << std::endl;
    while ( s.size() != 0 ) {
        Traits::shrink( s );
        if ( s.capacity() != lastSeen ) {
            std::cout << "  " << std::setw( 3 ) << s.size()
                << ": " << std::setw( 3 ) << s.capacity() << std::endl;
            lastSeen = s.capacity();
        }
    }
    std::cout << "Final: capacity = " << s.capacity() << std::endl;
}

struct Append
{
    static void grow( std::string& s )
    {
        s += 'x';
    }
    static void shrink( std::string& s )
    {
        s.erase( s.end() - 1 );
    }
    static std::string name()
    {
        return "Append";
    }
};

struct Assign
{
    static void grow( std::string& s )
    {
        s = std::string( s.size() + 1, 'x' );
    }
    static void shrink( std::string& s )
    {
        s = std::string( s.size() - 1, 'x' );
    }
    static std::string name()
    {
        return "Assign";
    }
};

int
main()
{
    test<Append>();
    test<Assign>();
    return 0;
}

Try it. The results are quite instructive.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜