How to free unused row capacity

I am dealing with a lot of lines in my program. This string data does not change over its entire life after it has been read in my program.

But since the C ++ line reserves capacity, they spend a lot of space that will not be used accurately. I tried to fill these spaces, but it did not work.

Below is the simple code I tried:

string temp = "1234567890123456"; string str; cout << str.capacity() << endl; str.reserve(16); cout << str.capacity() << endl; // capacity is 31 on my computer str += temp; cout << str.capacity() << endl; str.reserve(16); cout << str.capacity() << endl; // can't release. The capacity is still 31. 

(The compiler is Visual C ++)

How can I let him go?

+6
c ++ string memory-management visual-c ++
source share
8 answers

When you call reserve , you make a request for capacity change. Implementations will only guarantee that a number equal to or greater than this amount is reserved. Therefore, a request for capacity reduction can be safely ignored by a particular implementation.

However, I recommend that you consider whether this is a premature optimization. Are you sure you are really doing so many lines that this is the bottleneck for you? Are you sure that this is actually a memory that a bottleneck?

From the documentation for reserve :

This can expand or reduce the size of the storage space in the row, although note that as a result, the capacity after calling this function is not necessarily equal to res_arg but can be equal to or greater than res_arg , therefore, reduced requests may or may not actually reduce the allocated space in a specific library implementation. In any case, it never trims the contents of the string (for this purpose, see resizing or transparency, which change the contents).

+12
source share

Why don't you use a char array?

+5
source share

Highlight Naveen answer :

 string x = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"; cerr << x.capacity() << "\n"; // MSVC++: 63 g++: 52 // This tends not to work (although in theory it could): //x = "XYZ"; //cerr << x.capacity() << "\n"; // MSVC++: 63 g++: 52 // This tends to work (although in theory it might not): string("XYZ").swap(x); cerr << x.capacity() << "\n"; // MSVC++: 15 g++: 3 

Note that if the base allocator allocates more than n bytes when building a string length n (for example, rounding to the nearest 32, as MSVC ++ does), there is no way to force it to use fewer bytes. But you probably won’t want to do this, since this rounding is done to increase the efficiency of the dynamic memory allocation process, and it also has the side effect of concatenating short strings on average faster (since fewer redistributions are required to occur) .

+4
source share

Try the std::string tag to compress your strings:

 std::string( str.data(), str.size() ).swap( str ) 

Where str is the string you want to shorten to size.

+4
source share

I think you can use the swap method to free data. replace it with an empty empty string so that when you exit the area, the local string frees up memory.

+3
source share

This is basically a concrete implementation. The idea is to minimize memory allocation and fragmentation requests. It is easy to prove that by doubling the existing size every time a block expands, both distribution counting and memory fragmentation are minimized. Therefore, as a rule, the implementation of STL containers doubles the existing block upon expansion.

One thing you can do is use a custom allocator that will not allocate more than necessary, then create std :: string objects when you no longer need to manipulate them (or when you manipulate, just replace the new std: : sting object is basically what others have done in their answers), and finally, you can use a unified memory allocator to minimize memory fragmentation, lose weaknesses, and improve performance.

Cm:

http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4079 http://www.sjbrown.co.uk/2004/05/01/pooled-allocators-for-the-stl / http://www.codeproject.com/KB/stl/blockallocator.aspx

Search for "STL Allocator" and "Memory Pool"

+1
source share

There is no minimum capacity for std::string . You can request any required capacity by calling reserve , but a specific implementation only guarantees that the capacity is set to a certain amount greater or equal to the required size.

Here's a modified version of your program that tests several string compression methods:

 #include <string> #include <iostream> using namespace ::std; template< typename S > S & reserve_request( S & s, typename S::size_type n ) { s.reserve( n ); return s; } template< typename S > S & shrink_request1( S & s ) { s.reserve(); return s; } template< typename S > S & shrink_request2( S & s ) { S( s ).swap( s ); return s; } template< typename S > S & shrink_request3( S & s ) { S( s.c_str() ).swap( s ); return s; } template< typename S > void test( S & s ) { cout << s.capacity() << endl; } int main() { string temp = "1234567890123456"; // length 16 string str; test( str ); // 15 test( reserve_request( str, 16 ) ); // 31 test( str += temp ); // 31 test( reserve_request( str, 16 ) ); // 31 test( shrink_request1( str ) ); // 31 test( shrink_request2( str ) ); // 31 test( shrink_request3( str ) ); // 31 return 0; } 

It seems that Visual C ++ std::string usually saves some reserve capacity.

If your project loads a large number of lines read from an external source, the size of which never changes, you might be better off (as others suggested) to store them in one large block of character memory, separated by the characters '\0' (i.e. as C -line). If you like, you can provide wrapper functions that return std::string on the fly.

0
source share

the capacity will NEVER be less than 15 with the stink dinkumware STL. std :: basic_string has a union, which is a pointer to a dedicated buffer or 16-byte buffer (if capacity () <= 15) (for char strings)

see xstring header file

in the example that you specify where you reserve 16, you actually reserve 17 (one for null), which is> 16, so it is allocated rather than cached at 16 bytes in the cache pointer union. This distribution doubles the previous size (16), so you get 32. The capacity of this row is probably 31.

But it depends on the implementation of STL.

Changing the parameter of the dispenser template in the decl std :: basic_string template is not enough - the choice of when to allocate and how much is in std :: basic_string produces the NOT algorithm in the dispenser. Doubling the previous size (and reducing it at <1/4) is the standard material in the introduction to the algorithms - Cormen Lieserson Rivest Stein

Not sure about ego reduction in dinkumware .......

0
source share

All Articles