1

From Strings in Depth, I learn that the exact implementation of memory layout for the string class is not defined by the C++ Standard. But how come &string and &string[0] will have different memory addresses?

string variable("String Test");
cout << (void *) &variable << endl;         // 003EFE58
cout << (void *) &variable[0] << endl;      // 003EFE5C
cout << (void *) &variable[1] << endl;      // 003EFE5D
... ...

But they do share the same content, check out:

cout << ((string)*(&variable))[0] << endl;  // 'S'
cout << *(&variable[0]) << endl;            // 'S'

Can anyone explain what's going on here?

herohuyongtao
  • 49,413
  • 29
  • 133
  • 174
  • 5
    `string` is not an array type, it's a class type. This would work as expected if you declared an array of `char`s. –  Jan 25 '14 at 20:20
  • @H2CO3 correct, agree, removed confused because of printf – Grijesh Chauhan Jan 25 '14 at 20:22
  • @GrijeshChauhan **No!** The op asks for `std::string` ... – πάντα ῥεῖ Jan 25 '14 at 20:23
  • 2
    @GrijeshChauhan Yeah, not too good practice to use `printf()` in C++ code... –  Jan 25 '14 at 20:24
  • @H2CO3 How can I print the address of `&variable[1]` in C++ without using printf()? – herohuyongtao Jan 25 '14 at 20:26
  • @herohuyongtao `std::cout << (void *)&variable[1]` –  Jan 25 '14 at 20:27
  • Actually, that isn't right.. http://ideone.com/Qw91Gt and http://ideone.com/7saE8R – Brandon Jan 25 '14 at 20:29
  • @CantChooseUsernames Actually, I am right, and you don't know the difference between an **array** and a **pointer.** In your code, `str` is not an array, it's a pointer. –  Jan 25 '14 at 20:30
  • @H2CO3 Thanks, updated the question by removing `printf`. – herohuyongtao Jan 25 '14 at 20:31
  • @CantChooseUsernames And while we are throwing IDEOne links at each other's face (which is meaningless, a particular compiler cannot possibly be regarded as a C++ reference implementation): http://ideone.com/eDTKDs –  Jan 25 '14 at 20:34
  • 1
    Guess that is one of those flaws of having arrays and pointers being use interchangeably. `operator []` on a pointer and `operator []` on an array results in the same thing which is what confused me. – Brandon Jan 25 '14 at 20:37

3 Answers3

6

Because one is the address of the class instance, the other is the address of the first character, which is typically contained in dynamically-allocated memory managed by the class (or somewhere in the instance itself in the case of SSO).

Community
  • 1
  • 1
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
2

String is an object. It has some fields in its beginning. This is implementation specific. In your case there is just one 4 bytes field. The sting that it contains starts with an offset. In fact, the sting can be in a heap buffer. It may not be in the object itself.

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
  • 3
    It's not that "it has some fields in its beginning". The array is typically dynamically allocated, so there's really just a pointer to some other (completely unrelated) block of memory. –  Jan 25 '14 at 20:23
  • True. This is what goes on in 99% of cases. Should I distrust the listing in the original post? Maybe the reasons are still needed. – Kirill Kobelev Jan 25 '14 at 20:24
  • Not necessarily. In fact, who knows what a modern optimizing compiler with `std::string` intrinsics might do with a string instance constructed from a string literal. (e. g. turning it into a struct which contains an auto array instead of a dynamically allocated pointer...) –  Jan 25 '14 at 20:26
  • Then why you disprove my statement in your comment? – Kirill Kobelev Jan 25 '14 at 20:27
  • 1
    Because this is not the **typical** and **straightforward** reasoning. –  Jan 25 '14 at 20:27
0

This happens to confuse a lot of programmers, so I will do my best to explain it.

// here, you take the address (&) of the first item in the variable array...
//       you then convert that address to a string object
//       an implicit cast occure, which constructs a string instance and copies the contents of 
//       the referenced item in variable (which is a dereferenced char* char('S'))
//       this line is similar to:
//         char c = *(&variable[0]); // dereference
//         string S = string(c);     // copy
//         printf("%c\n", S);        // print
printf("%c\n", ((string)*(&variable))[0]);  // 'S'

// here, you do the same dereference of the first item in variable,
//       except you don't copy it into a string object
//       similar to
//         char c = *(&variable[0]);
//         printf("%c\n", c);
printf("%c\n", *(&variable[0]));            // 'S'
zackery.fix
  • 1,786
  • 2
  • 11
  • 20