What are differences between std::string and std::vector<char>?

  • vector<char> gives you a guarantee that &v[0]+n == &v[n] whereas a string doesn't (practically, it is the case, but there is no guarantee)... AFAIK C++0x gives that guarantee already
  • there is no implicit conversion from const char* to vector<char>
  • string is not an STL container. For example, it has no pop_back() or back() functions
  • And last, but not least, different member functions! String gives you functions suitable for strings, like returnig a null-terminated string with c_str()

Bottom line: Use string when you need to operate with strings. Use vector<char> when you need a ... well, vector of individual chars...

Another use of vector<char> is a way to avoid vector<bool> specialization.


std:string is used for string representation and has methods specific for string manipulation, like for example substr and compare.

And also you have the c_str method that will return a pointer to a valid "C string" that you can use as parameter for functions that only take a const char* as parameter, because it will guarantee that the returned string is zero terminated.

std::vector<char> will be only an array of chars and the biggest problem is because you do not have a c_str method, so you cannot pass it as parameter for functions that take a const char *, unless you take care of keeping a 0 at the end of the vector all the time.


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:

  1. 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.

  2. 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.)

  3. 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<>.

  4. 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.)

Tags:

C++