Why is sizeof(string) == 32?
Most modern std::string
implementations1 save very small strings directly on the stack in a statically sized char
array instead of using dynamic heap storage. This is known as Small (or Short) String Optimisation (SSO). It allows implementations to avoid heap allocations for small string objects and improves locality of reference.
Furthermore, there will be a std::size_t
member to save the strings size and a pointer to the actual char
storage.
How this is specifically implemented differs but something along the following lines works:
template <typename T>
struct basic_string {
char* begin_;
size_t size_;
union {
size_t capacity_;
char sso_buffer[16];
};
};
On typical architectures where sizeof (void*)
= 8, this gives us a total size of 32 bytes.
1 The “big three” (GCC’s libstdc++ since version 5, Clang’s libc++ and MSVC’s implementation) all do it. Others may too.
String size always 32 bytes
sizeof
is a compile time operator which returns the size in bytes of an object representation, which is the size of its layout in memory. It has nothing to do with the std::string
content.
Use string.size()
instead.
Why does Sizeof operator on a std::string yield unexpected result?
sizeof
of a std::string
instance just returns the size, in bytes, of the "internal representation" of the std::string
, i.e. you can think of it like the sum of the sizeof
s of each std::string
's data members (there may be padding involved as well).
For example, in 32-bit debug builds with VS2015, sizeof(std::string)
returns 28; in 64-bit debug builds I get 40; in 32-bit release builds I get 24, and in 64-bit release builds 32.
That's because the internal representation of std::string
changes with different build options: e.g. debug builds usually contain additional mechanics to help spotting bugs, which grows the size of the representation; moreover, in 64-bit builds the pointers are larger, so again the size increases with respect to 32-bit builds, etc.
So, the number you get from sizeof
invoked on a std::string
instance is in general different from the number of char
s that make the string's text. To get this number, you have to call std::string::size
or std::string::length
.
c++ sizeof( string )
It isn't clear from your example what 'string' is. If you have:
#include <string>
using namespace std;
then string
is std::string
, and sizeof(std::string)
gives you the size of the class instance and its data members, not the length of the string. To get that, use:
string s;
cout << s.size();
sizeof in c++ showing string size one less
sizeof(s)
gives you the size of the object s
, not the length of the string stored in the object s
.
You need to write this:
cout << s.size() << endl;
Note that std::basic_string
(and by extension std::string
) has a size()
member function. std::basic_string
also has a length
member function which returns same value as size()
. So you could write this as well:
cout << s.length() << endl;
I personally prefer the size()
member function, because the other containers from the standard library such as std::vector
, std::list
, std::map
, and so on, have size()
member functions but not length()
. That is, size()
is a uniform interface for the standard library container class templates. I don't need to remember it specifically for std::string
(or any other container class template). The member function std::string::length()
is a deviation in that sense.
Related Topics
Run an Application in Gdb Until an Exception Occurs
How to Get Current Timestamp in Milliseconds Since 1970 Just the Way Java Gets
How Does the Range-Based for Work for Plain Arrays
What Is the Simplest Way to Convert Array to Vector
Common Array Length MACro for C
A C++ Implementation That Detects Undefined Behavior
Fast Cross-Platform C/C++ Image Processing Libraries
Narrowing Conversions in C++0X. Is It Just Me, or Does This Sound Like a Breaking Change
Are There Practical Uses for Dynamic-Casting to Void Pointer
Error: Use of Deleted Function
Linking Different Libraries for Debug and Release Builds in Cmake on Windows
Problems with Singleton Pattern
Floating Point Comparison Revisited
Pass by Value VS Pass by Rvalue Reference