Why can't I write to a string literal while I *can* write to a string object?

Solution 1:

Because "Hello" creates a const char[]. This decays to a const char* not a char*. In C++ string literals are read-only. You've created a pointer to such a literal and are trying to write to it.

But when you do

string s1 = "hello";

You copy the const char* "hello" into s1. The difference being in the first example s1 points to read-only "hello" and in the second example read-only "hello" is copied into non-const s1, allowing you to access the elements in the copied string to do what you wish with them.

If you want to do the same with a char* you need to allocate space for char data and copy hello into it

char hello[] = "hello"; // creates a char array big enough to hold "hello"
hello[0] = 'w';           //  writes to the 0th char in the array

Solution 2:

string literals are usually allocated in read-only data segment.

Solution 3:

Because Hello resides in read only memory. Your signature should actually be

const char* s1 = "Hello";

If you want a mutable buffer then declare s1 as a char[]. std::string overloads operator [], so you can index into it, i.e., s1[index] = 'w'.

Solution 4:

Time to confuse matters:

char s0[] = "Hello";
s0[0] = 'w';

This is perfectly valid! Of course, this doesn't answer the original question so here we go: string literals are created in read-only memory. That is, their type is char const[n] where n is the size of the string (including the terminating null character, i.e. n == 6 for the string literal "Hello". But why, oh, why can this type be used to initialize a char const*? The answer is simply backward compatibility, respectively compatibility to [old] C code: by the time const made it into the language, lots of places already initialized char* with string literals. Any decent compiler should warn about this abuse, however.