3

I tried the below program:

#include <iostream>
#include <string>

int main ()
{
  std::string str;
  str[0] = 'o';
  str[1] = 'k';
  std::cout << str.length();
  std::cout << "as a whole :";
  std::cout << str << std::endl;
  std::cout << "character by character :";
  std::cout << str[0] << str[1] << std::endl;      
  return 0;
}

I do not understand why I can not print the string as a whole using the object variable and why the length is returning as 0 since clearly I have added the characters using the subscript operator as that would return char reference so I know that is legal.

In addition, I did not get any kind of exception. So there is that. Obviously, there is a lot happening behind the scenes in the std::string class and I know I am missing something. Could someone help me with this?

JeJo
  • 30,635
  • 6
  • 49
  • 88

3 Answers3

5

I don't understand why I can't print the string as a whole [...]...

Because you are experiencing the undefined behaviour.

This

std::string str;

construct a default string with 0 allocations of memory. Meaning modifying via std::string::operator[] will cause a asses out of bounds undefined behaviour. Therefore, anything could happen. In your case, the length returns 0.


[...] clearly I have added the characters using the subscript operator as that would return char reference so I know that is legal.

No, you have not, for the reason mentioned above. For the reference, the std::string::operator[]

Returns a reference to the character at specified location pos. No bounds checking is performed. If pos > size(), the behavior is undefined.


As possible fixes, you might want to std::string::resize before, accessing the elements.

#include <string>

std::string str;
str.resize(2);
str[0] = 'o';
str[1] = 'k';
// ... now it has defined behaviour

or std::string::push_back each charector into the string.

#include <string>

std::string str;
str.push_back('o');
str.push_back('k');
// ... now it has defined behaviour
JeJo
  • 30,635
  • 6
  • 49
  • 88
  • Note that you can access `str[0]` for a default-constructed `str`. You just may not modify it. – Daniel Langr Nov 11 '19 at 07:35
  • Agree, just wanted to technically clarify your statement. BTW, note that your link to cppreference is not related here. UB is, in this case, caused by different clauses from the Standard. Namely [this](http://eel.is/c++draft/string.access) and [this](http://eel.is/c++draft/library#res.on.required-2). No _out-of-bounds array access_ is involved here by the Standard (it may be, internally, but this is undefined). – Daniel Langr Nov 11 '19 at 07:45
5

You have a string of length 0 and then you try to modify its contents using the subscript operator. That's undefined behavior, so at this point, no particular outcome is guaranteed. If you used at() instead, it would have exposed the mistake and thrown an exception instead.

why the length is returning as 0

It started out as 0 and you didn't do anything to add to it (such as push_back or +=). But then again, since what you did earlier was undefined behavior, anything could have happened here.

In addition, I didn't get any kind of exception.

You can try std::string::at instead, which will throw an std::out_of_range exception when you try that.

Blaze
  • 16,736
  • 2
  • 25
  • 44
  • Thanks. I am still doubtful of str[pos] returns the character at that position ? – Prithivi Raj Nov 11 '19 at 09:42
  • It does return a reference to the character at that position, but you have to ensure that the string is actually that long before you do that. – Blaze Nov 11 '19 at 09:43
3

You added nothing to the empty string str. Instead, you're trying to edit non-existing element of the empty string. Subscript operator of std::string does not add element automatically. (unlike std::map) Moreover, it is not guaranteed that subscript operator throws some exception. If you want safe-subscript-operation, You can use std::string::at function.

You can use += operator to append something to your string.

str += 'o';
str += 'k';
ikh
  • 10,119
  • 1
  • 31
  • 70
  • _it is not guaranteed that subscript operator throws some exception_ Exact opposite: [it's guaranteed that subscript operator will not throw any exception](http://eel.is/c++draft/basic.string#string.access-3). – Daniel Langr Nov 11 '19 at 07:32
  • but isn't it weird when I access the character through subscript it is returning the correct character? where does it get it? – Prithivi Raj Nov 11 '19 at 09:44
  • @PrithiviRaj It is, indeed. But that's still just sheer luck, you were probably writing into the internal structure of the string object (I'm thinking of [small-string optimization](https://stackoverflow.com/questions/21694302/what-are-the-mechanics-of-short-string-optimization-in-libc)). – Sz. Feb 22 '23 at 17:28