C ++ string size is not updated after assignment

int main(int argc, char const *argv[]) { const char *s1 = "hello"; string s2; s2 = s1; s2.reserve(10); s2[5] = '.'; s2[6] = 'o'; s2[7] = '\0'; cout << "[" << s1 << "] [" << s2 << "]" << endl; return 0; } 

The above code does not print s2 correctly. Instead of hello.o it always prints hello . It seems that size s2 remains at 5 always after the first assignment. Why is this so?

+5
source share
5 answers

operator[] does not resize the string. And your calls to them with indices 5, 6 and 7 are out of range and undefined. Use resize to set the string to a specific size, or push_back or operator+= to add characters.

Also note that you do not need to zero out the end of std::string manually. The class will handle this on its own. Although you are allowed to have inline zeros if you really want to, and they will be considered as part of the string length.

+10
source

s2.reserve(10); does not produce a string at all, it just tells the container to reserve enough memory for at least 10 characters, It fills nothing with the reserved space.

Therefore, when indexing s2[5] you are essentially indexing outside the "used" row (ie its size), this behavior is undefined.

To resize, you can use s2.resize(10); . This will correctly distribute and populate the string, and it will have a size of 10 . To select and insert a character at the same time, you can also use push_back() or operator+= .

On the side note: s2[7] = '\0'; not required. The string class internally manages any NUL terms that are needed for methods like c_str() , etc. You do not need to add NUL yourself.

+6
source

You should use s2.resize() instead of s2.reserve() .

+4
source

std::string::reserve only allocates memory, but does not change the size of the string. In your example:

 s2 = s1; // Resize string to 6 characters s2.reserve(10); // Allocate another 4 char, but not resize s2[5] = '.'; // Write '.' to some memory, but the string is still not resized. 

A simple fix is ​​to use std::string::resize instead of reserve .

+2
source

Short answer: use resize (10) instead of reserve (10)

Long answer: When implementing std :: string, there are two sizes and capacity of variables. Capacity is the amount of memory that you allocated for the row. Size - how many valid elements (in your case, char) are allowed in your string. Please note: capacity will always be less than or equal to size. When you call reserve (), you change capacity. When you resize (), you can not only resize, but also change the capacity if the size> capacity, in which this formula will be applied:

 if (size > capacity){ capacity = max(size, capacity*2); //Why multiply capacity by 2 here? This is to achieve amortized O(1) while resizing } 

Here is a code example of what the OP wants, and another code to better explain the size and capacity

 #include <iostream> #include <string.h> using namespace std; int main(int argc, char const *argv[]) { const char *s1 = "hello"; string s2; s2 = s1; cout << "length of s2 before reserve: " << s2.length() << endl; cout << "capacity of s2 before reserve: " << s2.capacity() << endl; s2.reserve(10); cout << "length of s2 after reserve: " << s2.length() << endl; //see how length of s2 didn't change? cout << "capacity of s2 after reserve: " << s2.capacity() << endl; s2.resize(8); //resize(10) works too, but it seems like OP you only need enough size for 8 elements cout << "length of s2 after resize: " << s2.length() << endl; //size changed cout << "capacity of s2 after resize: " << s2.capacity() << endl; //capacity didn't change because size <= capacity s2[5] = '.'; s2[6] = 'o'; s2[7] = '\0'; cout << "[" << s1 << "] [" << s2 << "]" << endl; // You're done // The code below is for showing you how size and capacity works. s2.append("hii"); // calls s2.resize(11), s[8] = 'h', s[9] = 'i', s[10] = 'i', size = 8 + 3 = 11 cout << "length of s2 after appending: " << s2.length() << endl; // size = 11 cout << "capacity of s2 after appending: " << s2.capacity() << endl; //since size > capacity, but <= 2*capacity, capacity = 2*capacity cout << "After appending: [" << s1 << "] [" << s2 << "]" << endl; return 0; 

Result:

 length of s2 before reserve: 5 capacity of s2 before reserve: 5 length of s2 after reserve: 5 capacity of s2 after reserve: 10 length of s2 after resize: 8 capacity of s2 after resize: 10 [hello] [hello.o] length of s2 after appending: 11 capacity of s2 after appending: 20 After appending: [hello] [hello.ohii] 
0
source

Source: https://habr.com/ru/post/1242749/


All Articles