cout << sizeof(std::string) << endl;
我的64位计算机上的结果为8,与sizeof(char*)
相同,所以我假设字符串类只存储char*
。那么,如何实现尺寸功能?它是否使用strlen
(因为它没有存储实际大小或指向结束字节的指针)?
在this page上,它显示尺寸函数具有恒定的时间复杂度,所以我很困惑。在another page上有人有更大的字符串大小。
我在Fedora 64位上使用GCC 4.7.1。
答案 0 :(得分:10)
可能有很多解释。只是因为std::string
恰好存储了一个指针而没有其他任何东西并不意味着这必然是指向受控序列的char *
指针。你为什么跳到那个结论?
很容易证明你的std::string
是一个PImpl风格的包装器,用于指向存储所有内部家庭数据的内部对象的指针,包括char *
指针,长度和其他任何内容必要。这样,内部对象可以任意大,而不会对std::string
本身的大小产生任何影响。例如,为了便于快速引用计数复制,在一些实现中,std::string
可以与std::shared_ptr
类似地实现。即在这种情况下,std::string
基本上会变成std::shared_ptr<std::string_impl>
,并添加了写时复制语义。
目标“字符串实现”对象甚至可能使用“struct hack”样式方法来存储实际字符串,这意味着它不是存储char *
指针,而是可以将整个字符串嵌入到自身的末尾。 / p>
答案 1 :(得分:6)
查看libstdc ++的doxygen docs:
_CharT* _M_p; // The actual data
假设std::basic_string<char>
,_M_p
是指向实际数据的char*
指针,这就是您获得8
的原因。
它甚至说:
_M_p指向字符串中的第一个字符,而你 将它转换为指向_Rep的指针并减去1以获得指向的指针 报头中。
因此,它隐藏了一个指向存储字符串数据之前的内存块中的实际表示(容量,长度等)的指针。
然后,有以下成员函数来获取表示:
Rep* _M_rep() const
{ return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); }
然后他们就像_M_rep()->_M_length;
一样调用它来获取size
。
答案 2 :(得分:0)
你假设std :: string是char *是错误的。以下是sizeof(std :: string)== sizeof(char *)的几个可能实现之一:
struct std::string
{
string_implementation
{
size_t size;
size_t buffer_size;
char_traits whatever;
char *buffer; // Here is your actual string!
};
string_implementation *ptr;
}
答案 3 :(得分:0)
std::string
是typdef
的{{1}},std::basic_string<char>
已在文件basic_string
中定义(在我的计算机上)。该文件中有很多间接,但粗略地说/usr/include/c++/4.4/bits/basic_string.h
存储指向实际数据的指针
std::string
这就是你观察到这种行为的原因。可能会对此指针进行转换以获取指向结构的指针,该结构描述了众所周知的字符串属性(位于实际数据前面):
// Use empty-base optimization: http://www.cantrip.org/emptyopt.html
struct _Alloc_hider : _Alloc
{
_Alloc_hider(_CharT* __dat, const _Alloc& __a)
: _Alloc(__a), _M_p(__dat) { }
_CharT* _M_p; // The actual data.
};