So what are main differences and which of them will be used in which cases?
So what are main differences and which of them will be used in which cases?
A std::vector<char> can be used as if it were a std::string, but the reverse is not true.
A std::vector<char> just stores sequences of characters, but not all sequences of characters are strings. Consider binary data, which would be correctly stored in a std::vector<char> (or std::vector<unsigned char>); it wouldn't make sense to store this in a string.
Internally, std::string could be implemented in much the same way as std::vector<char>—and, indeed, you can think of it as being the same conceptually—but, in practice, there are a few important differences:
C++11 introduced the requirement that a std::string is required to store a NUL-terminated sequence of characters internally. That brings it into compliance and makes interoperating with C-style strings easier. Obviously, std::vector<char> would not have that requirement associated with it, and you wouldn't want it to.
std::string offers a very different and much expanded interface compared to std::vector<>. While the latter is just a boring old sequence of elements, the former is actually designed to represent a string and therefore offers an assortment of string-related convenience functions. (Some would argue too many, preferring instead if these had been implemented as standalone, "free" functions, rather than member functions of a special "string" class.)
Common implementations of std::string will use an optimization called the "small string optimization (SSO)", which avoids dynamic memory allocation when you are storing a string that will fit directly within the std::string object instance. You won't find this optimization in std::vector<> (although it could actually be implemented in a custom vector type).
And, in order to enable the small-string optimization, the standard requires that swapping a std::string invalidate its iterators. That requirement does not apply to std::vector<>.
Although perhaps only a historical curiosity now (especially since almost no implementations of the standard library worked this way in practice), in C++03 and previous versions of the language standard, std::string was not required to store the characters in the string in contiguous memory. In other words, it didn't actually have to be implemented as a wrapper around an array. This allowed something like the rope data structure and/or a copy-on-write strategy to be used under the hood. std::vector<> has always required contiguous storage of its elements. (C++11 introduced the same requirement for std::string.)