5

When you access elements of an array using array[i], I thought that C++ would take the starting position of the array in memory and add i*sizeof(one array element) and then dereference that address (or do something equivalent to what I just described). However, it seems to me that if you have an array of strings (std::string), each element could be a different size based on the number of characters in the string, so there must be something else going on.

Also, to my understanding, array elements are stored in contiguous memory. If you had strings stored in contiguous memory and then appended more characters to one of them, all of the succeeding strings would have to be moved over.

Can someone explain to me how this works?

6
  • Post some working code examples. There is a difference between "an array of chars" and "array of std::string" and "array of [pointers to] chars", etc. Commented May 30, 2011 at 22:59
  • When I say string I mean std::string, not char*. Commented May 30, 2011 at 23:01
  • @pst: Not seen the phrasing "stdstr" used before. Interesting. Commented May 30, 2011 at 23:01
  • Changed "why" to "how" in the title; subtly alters the question's meaning. Commented May 30, 2011 at 23:02
  • I was debating on whether to use "why" or "how" myself, actually. Commented May 30, 2011 at 23:05

7 Answers 7

7

The string size is constant, but it (at some level) has a pointer to some non-constant-sized data.

The pointer size is constant, the pointee size is not.

Sign up to request clarification or add additional context in comments.

Comments

4

std::strings are objects. The size of one std::string is the same as the size of another std::string. They indirectly "contain" their data via dynamic allocation, which does not affect the size of the owning object.

Similarly, if you mean C-style strings, you actually only pass around char* (or pointers-to-char). Pointers are always the same size, no matter the length of the block of memory to which they point.

2 Comments

I think it's important to note here that because it's the size of pointers that matters, this also means it's possible to have things like char **, as you do in main(int argc, char **argv), and iterate those char pointers to get the actual char strings.
@MikeBantegui: Yes, that's a pointer to the first element in an array of C-style strings. It's what I spoke about in my second paragraph. What's really important to note here is that char*[N] is not the same as char[N][M].
2

std::string is a wrapper of char*, not an array. Arrays can be different sizes, yes, but char*s are pointers and have a constant size. The char* that std::string encapsulates points to dynamically allocated memory. This is why sizeof(std::string) returns the same size no matter how large the string grows.

1 Comment

They don't have to be 4 or 8 bytes.
1

If you're refering to the C++ type std::string, each one of the elements of an array of strings occupy the same ammount of memory. However, each string may contain a pointer pointing to a different position in the memory, of different length, where it actually stores the string.

To see an example (sample code), imagine the std::string class something like this:

struct string
{
  size_t length;
  const char* data;
  // other members..
};

Note how the structure size is always the same (a size_t and a pointer), but the memory pointed to, where the actual string is stored, may be different.

Comments

1

The string object has a size and that will differ depending on your implementation complier etc. You are correct in your assessment of who c++ handles arrays, but overlook pointer data. The string class in its bowels has a pointer to some heap data that heap data can be of any arbitrary size, but the pointer to that data is a fixed size. So inside the data layout of a string there is a way for the complier to create uniform objects with non fixed representation data.

Comments

0

Since a string is a character pointer, an array of strings is an array of (char *) — a contiguous vector of (char *) pointers. Modifying a string would modify the memory pointed to by each element. Now, if you declared it to be statically allocated:

char foo[10][10];

then in terms of memory layout it's indistinguishable from

char foo2[100];

and it would be possible to corrupt memory by writing past the declared size; this is one reason one should use std::string instead of C-style strings, which are perhaps the best example of why C is a lousy language for application programming. (An array of std::string would be an array of objects, each of which would have a (char *) stored in it somewhere that you wouldn't need to worry about — std::string does it for you, and much more reliably.)

Comments

0

This is how you would do it in code...

const int ARRSIZE = 5;
string arrayOfStr[ARRSIZE] = {"one", "two", "three"};

for (int i = 0; i < ARRSIZE; ++i)
{                 
    cout << arrayOfStr[i] << endl;                  
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.