0

I guess I'm still not understanding the limitations of C++ containers and arrays. According to this post and this It is impossible to store items of dynamic size in an STL vector.

However with the following code I can dynamically re-size an element of a vector with the results one would expect if it was ok to have items of varying and changing size in a vector.

string test = "TEST";
vector<string> studentsV;

for (int i = 0; i < 5; ++i)
{
    studentsV.push_back(test);
}

studentsV[2].resize(100);

for (string s : studentsV)
{
    cout << s << "end" << endl;
}

Result:

TESTend
TESTend
TEST
                    end
TESTend
TESTend

I can re-size the string element to any size, and it works fine. I can also do the same with a regular C-style array. So, what is the difference between the above posts and what I am doing, and can you give an example of what "dynamic item size" really means, because apparently I am not understanding.

Community
  • 1
  • 1
Steve M
  • 9,296
  • 11
  • 49
  • 98
  • What makes you think that a `std::string` instance has a dynamic size ? What if the data is actually implemented as a member pointer to dynamic memory ? – SirDarius Jan 12 '14 at 20:58
  • 1
    `sizeof(std::string)` is not the same as `std::string::size`. – GManNickG Jan 12 '14 at 21:00
  • Good point. How would I find how which things are implemented like that and are safe to use in a vector? – Steve M Jan 12 '14 at 21:00
  • 1
    C++ does not have dynamically sized classes. Every class has a defined size, which is known at compile time. – Benjamin Lindley Jan 12 '14 at 21:03
  • @svenoaks It's perfectly safe to use these classes in a vector. Even a vector itself can be the element type of another vector. – paddy Jan 12 '14 at 21:07

3 Answers3

2

A std::string uses dynamic memory to increase the size of the string being stored. This is not what those articles are talking about.

What they mean, is that sizeof(std::string) is constant. The actual object representing a std::string will always have the same size, but it might do additional allocations in another part of memory.

A std::vector is really just a friendly wrapper around a dynamically-sized array. The definition of an array in C or C++ is a contiguous block of memory where all elements are of equal size.

paddy
  • 60,864
  • 6
  • 61
  • 103
  • I see. I notice that trying to put C-style arrays of varying size in vector leads to a compiler error, because they do not have such dynamic memory. – Steve M Jan 12 '14 at 21:11
  • VLAs are not really dynamic, even though they look like they are. – paddy Jan 12 '14 at 21:25
1

can you give an example of what "dynamic item size" really means, because apparently I am not understanding.

This is the core of your question.

Namely: if all C++ classes (even ones that manage dynamic memory as part of their implementations) have a fixed and known footprint size via sizeof()...just what sort of thing is it that you can't put in a std::vector?

Since something like a std::string and a std::bitset are classes of different sizes, you couldn't have a vector of [string string bitset string bitset string]. But the type system already wouldn't let you do that. So that can't be what they're talking about.

They're just saying there's no hook for supporting structures like this from the C world:

struct packetheader {
   int id;
   int filename_len;
};
struct packet {
   struct packetheader h;
   char filename[1];
};

You couldn't make a std::vector<packet> and expect to find some parameter to push_back letting you specify a per-item size. You'd lose any data you'd allocated outside of the structure boundary.

So to use something like that, you'd have to do std::vector<packet*> and store pointers.

  • I don't get your example - isn't packetheader fixed size, and char filename[1] is fixed size, so why isn't packet fixed size? – Steve M Jan 12 '14 at 21:14
  • @svenoaks Packet is fixed size. But that pattern was a way of making structures in C that had headers you could examine, yet would be variable-sized with respect to the last field. So the "effective size" of packet would be larger *(in this case the size of the header plus the size of the string.)* Hence the memory used is larger than sizeof(packet), and if you were to copy the structure you'd have to take the `filename_len` into account. C++ doesn't do things this way, and hence the standard collection classes won't let you specify any kind of "hook" for how large your item "actually" is. – HostileFork says dont trust SE Jan 12 '14 at 21:19
0

The size of std::string is not dynamic. std::string is probably implemented with a pointer to a dynamically allocated memory. This makes sizeof(std::string) static and possibly different from the size of the actual string.

Shoe
  • 74,840
  • 36
  • 166
  • 272