delete is used to de-allocate objects originally allocated with new. delete[] is used to de-allocate arrays originally allocated with new[].
You didn't use new in your first line, so shouldn't use delete in the second.
Specifically,
char *str = "hi";
allocates memory for a pointer called str, which has automatic lifetime. Automatic here means the compiler takes care of it for you.
The pointer points to a string literal, "hi", which was statically allocated once, at compile time, and can never be changed. In fact, your pointer should be const.
Now, if we change your code to
std::string str = "hi";
a dynamic allocation does happen since std::string makes a copy of your string literal, but it also takes care of releasing that copy for you. It may well use new[] and delete[] internally.