0

I am stuck on this stupid doubt and can't understand which part have I understood wrong. I am trying to fill an empty string and I thought of doing it using the subscipt [] operator but found that although loop runs perfectly but the final string is still empty with size zero. However push_back runs perfectly fine. I can use push_back but want to understand the reason for the first one. If anyone can clarify?

string r;
int i;
for(i = 0; i < 5; ++i)
{
     r[i] = 'a';
}
cout << r.size();    //output: 0
cout << endl;

for(i = 0; i < 5; ++i)
{
    r.push_back('a');
}
cout << r.size();    //output: 5
anas16
  • 68
  • 10
  • 1
    Your first for-loop is undefined behavior. You can't assign a char at an index >= to the string's length. The string `r` is initially empty and hence has 0 length. – selbie Jul 12 '22 at 19:31
  • 2
    `push_back` adds a new element to the string. `[]` is used to access an existing element, so doesn't work when the string is empty. – BoP Jul 12 '22 at 19:33
  • 3
    `[]` doesn't add anything to a `string`. It just writes over whatever was already there. If there wasn't anything there... That's bad. – user4581301 Jul 12 '22 at 19:34
  • 1
    Use `r.at(i)` instead of `r[i]` to avoid undefined behavior. – MikeCAT Jul 12 '22 at 19:34
  • But when I access ```r[0]```, I get the correct output. Shouldn't I get garbage? – anas16 Jul 12 '22 at 19:40
  • 1
    There is no good way to predict what you'll get. Some libraries add extra checks into the debug version of the library and make the problem easier to find by spitting out an error message and then aborting the program. `r[0]` could hold exactly what you wrote because you got unlucky and managed to hit a writeable location. But you could find some time later that you wrote over some other variable and now the program crashes somewhere completely unrelated. Those can be a to untangle. You can't count on anything recognizable in the general sense. – user4581301 Jul 12 '22 at 19:59
  • 1
    *Shouldn't I get garbage?* -- Maybe the output *is* garbage, and it so happens it is equal to what you wanted. – PaulMcKenzie Jul 12 '22 at 22:04

1 Answers1

1

As simple as it is for std::vector, std::string doesn't have bounds check when using subscript operator. When creating empty string, you have a container of zero length, thus when you assign values by index, the values are assigned to memory out of the collection's bounds

The Dreams Wind
  • 8,416
  • 2
  • 19
  • 49
  • What are you trying to get at with *As simple as it is for std::vector, std::string doesn't have bounds check when using subscript operator.*? `std::vector` doesn't do bounds checks either in the subscript operator. – NathanOliver Jul 12 '22 at 19:34
  • @NathanOliver I'm just saying that it works the same way. Just treat `std::string` a special kind of a collection, which acts like `std::vector` in this case – The Dreams Wind Jul 12 '22 at 19:35
  • But while accessing, it gives correct value which was stored. Shouldn't there be a garbage value from memory? – anas16 Jul 12 '22 at 19:43
  • 1
    @Mohd.Anas first of all it's undefined behaviour. I.e. it won't be consistent between different version of compilers (or even between different runs with the same compiler). In your case i can't see how you read the data, but I assume the compiler just writes the data you give to the memory which does not belong to the string, so it means it may change at any point during runtime later on – The Dreams Wind Jul 12 '22 at 19:48
  • *Shouldn't there be a garbage value* -- What is a "garbage value"? 0? 1? 2? -- They are all "garbage values" if you access a vector out-of-bounds. Just because the values look "simple" doesn't mean they are not garbage. – PaulMcKenzie Jul 12 '22 at 22:07
  • @PaulMcKenzie Actually I was getting the same value which I tried to store, that's why I got confused. – anas16 Jul 13 '22 at 18:39