22

So what are main differences and which of them will be used in which cases?

Mihran Hovsepyan
  • 10,810
  • 14
  • 61
  • 111
  • 1
    I don't see any good use for std::vector – Adrian Jul 01 '11 at 12:38
  • 3
    @vBx Now you see http://stackoverflow.com/questions/4761529/efficient-way-of-reading-a-file-into-an-stdvectorchar – Mihran Hovsepyan Jul 01 '11 at 12:57
  • They are different containers. They may share a great deal of similarity, but that's the end of it. Try calling the `c_str()` member of a `std::vector` object. – Adrian Mole Dec 12 '20 at 13:01
  • internally they are both a dynamic array of `char`s, but their interface is quite different. Take a look at https://en.cppreference.com/w/cpp/string/basic_string and https://en.cppreference.com/w/cpp/container/vector. – 463035818_is_not_an_ai Dec 12 '20 at 13:02
  • `string` maintains an extra byte at the end of vector that is always set to 0. It doesn't include that byte when you call `size()`. However, it is there in the `c_str()` operator so that it doesn't have to make a copy of the data each time c_str is called. – Brannon Dec 12 '20 at 13:03
  • frankly, I don't believe it would be very useful to write an answer by listing all methods that `std::string` has but not `std::vector` and vice versa. Study the docs, and consider that they convey different meaning. A `std::vector` is just a vector of `char`s and the `char`s can be just numbers or a bunch of characters, while a `std::string` is a string, thats what you typically use for text – 463035818_is_not_an_ai Dec 12 '20 at 13:05
  • At the implementation level, the `std::string` class *may* make use of functions such as `strcmp` and the like (though it doesn't *have* to). – Adrian Mole Dec 12 '20 at 13:05

5 Answers5

27
  • 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.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 1
    Ok thanks @Armen. And what about binary data, can I keep it in string? will this work on all platforms `str += "\01512";`? – Mihran Hovsepyan Jul 01 '11 at 12:43
  • 2
    @Mihran: how's that binary? It'll append the character you mentioned to the string – Armen Tsirunyan Jul 01 '11 at 12:46
  • 1
    But can't it make string from right operand "\01512" in wrong way (i.e. empty string, because the literal starts with \0) and then concat this empty string to our `str`? – Mihran Hovsepyan Jul 01 '11 at 12:48
  • Ah, yes, indeed, you're right, in this case it won't append anything. But you can push_back() individual chars one at a time. Null-termination is not an issue for string that takes `const char*`, but the constructor of the string reads exactly before a '\0' – Armen Tsirunyan Jul 01 '11 at 12:52
  • 5
    There is a string constructor that takes the start and end iterators of the string and it will honour that length even if there are embedded null characters in that string. std::string operations will also treat the embedded null as part of the string. The problem will be when you pass the string to other objects that use it like a C string. – tinman Jul 01 '11 at 12:58
  • I think `deque` would be a better replacement for `vector` in terms of type safety, the performance price is very small. That is, if you don't need binary compatibility with C. – Sebastian Mach Jul 01 '11 at 15:19
  • @phresnel: How is deque more type safe then vector? oO – Armen Tsirunyan Jul 01 '11 at 17:00
  • @Armen Tsirunyan: I wrote not `deque`, but `deque`; i.e. `bool` is better than `char` if what you mean is `bool` and not `char`. Meyers also recommends that when you don't need binary layout compatibility with C. Very much the same reasoning about having `bool` in the first place. Sidenote: "oO"?. – Sebastian Mach Jul 02 '11 at 05:32
  • 9
    C++11 has added `pop_back()` and `back()` among others. – Drealmer Jan 05 '14 at 16:31
  • @Armen Tsirunyan " vector 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)"I do not understand why in vector it is guaranteed and in string it is not guaranteed (what is in vector and is not in string ? ) if you are sure that is this the true explain it please And if you will answer "now it is guaranteed" okay can you explain why was not it guaranteed in the past And if you knew that it was guaranteed and it will because no difference between vector,string(except functions members) please edit your comment – Fady Hany Nov 07 '21 at 06:40
  • @Armen Tsirunyan You said "practically, it is the case, but there is no guarantee" did you mean in 100% of the cases (In string o ) (&o[0]+n==&o[n]) that makes it a rule (make it guaranteed) ???? I am really do not understand can you explain this else? – Fady Hany Nov 07 '21 at 06:41
  • @FadyHany: Since C++11, you have an actual guarantee, in the standard. Before, you had no written guarantee, but practically that equality held on all implementations – Armen Tsirunyan Nov 08 '21 at 07:03
  • @Armen Tsirunyan Is this exactly what you mean ? " before c++11 you had logical guarantee that is (In string o) (&o[0]+n==&o[n] ) because string is a vector with special functions and this logical guarantee mean " In 100% of cases(implementations) (In string o) (&o[0]+n==&o[n] ) And there is no possibility of inequality " but you did not have a written guarantee in the standard but since c++11 you have logical guarantee that is (In string o) (&o[0]+n==&o[n] ) because string is a vector with special functions and you have a written guarantee in the standard – Fady Hany Jan 01 '22 at 17:27
  • @FadyHany: "because string is a vector". Well, no it is not. string is a basic_string, allocator>. String will append a null terminator to a given sequence of characters passed via iterator range. There are real differences between string and vector. One of those differences is that in C++03 there was no written guarantee for contiguity in string. That was just a bug in the standard though, which was fixed, the guarantee was of course meant to be there. – Armen Tsirunyan Jan 03 '22 at 09:13
  • @Armen Tsirunyan there is written guarantee for contiguity in string now ,right? – Fady Hany Jan 03 '22 at 12:24
  • @FadyHany: Yes, starting from C++11 – Armen Tsirunyan Jan 03 '22 at 13:16
5

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.

ilya1725
  • 4,496
  • 7
  • 43
  • 68
bcsanches
  • 2,362
  • 21
  • 32
  • Functions similar to `substr` exists for vectors as well, though, namely `std::copy`. –  Apr 07 '15 at 08:36
  • Yes, but they are not member functions, like substr. I can also use std::copy with std::string. – bcsanches Apr 09 '15 at 02:23
3

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

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
1

std::string is optimized for typical string processing operations, see e.g. the last section of http://www.cplusplus.com/reference/string/string/ "String operations".

std::vector is a generic container for any type data not only characters, and thus is has no specific support for what people usually only do with strings of characters.

Functions intended to work with character strings will typically support for string but not vector<char>.

Szabolcs
  • 24,728
  • 9
  • 85
  • 174
  • I'm not asking what is std::string and what is std::vector. – Mihran Hovsepyan Jul 01 '11 at 12:29
  • If your data represents a piece of text, use `string` as it was made for this purpose and has support for operations that people typically do with text. But of course you know this. Your question is not clear to me. – Szabolcs Jul 01 '11 at 12:33
1

Why do you want to compare this different data types? std::string is a library, to provide simple stringhandling like this:

std::string myString;
myString = "My Funny Text";
size_t startOfFunny = myString.find("Funny");

There are no string manipulation functions for std::vector as it is only a type of container. You would use this if you need to store chars independent from each other.

Thomas Berger
  • 1,860
  • 13
  • 26