C++ 为什么sizeof(string)==32?

C++ 为什么sizeof(string)==32?,c++,string,C++,String,字符串结构中导致sizeof()为32的开销是什么?最新的std::string实现1将非常小的字符串直接保存在堆栈上的静态大小char数组中,而不是使用动态堆存储。这被称为(SSO)。它允许实现避免为小字符串对象分配堆,并改进引用的局部性 此外,将有一个std::size\u t成员来保存字符串大小和一个指向实际char存储的指针 具体实现方式有所不同,但有以下几点: template <typename T> struct basic_string { char* beg

字符串结构中导致sizeof()为32的开销是什么?

最新的
std::string
实现1将非常小的字符串直接保存在堆栈上的静态大小
char
数组中,而不是使用动态堆存储。这被称为(SSO)。它允许实现避免为小字符串对象分配堆,并改进引用的局部性

此外,将有一个
std::size\u t
成员来保存字符串大小和一个指向实际
char
存储的指针

具体实现方式有所不同,但有以下几点:

template <typename T>
struct basic_string {
    char* begin_;
    size_t size_;
    union {
        size_t capacity_;
        char sso_buffer[16];
    };
};
模板
结构基本字符串{
字符*开始;
大小\u t大小\u;
联合{
尺寸和容量;
字符sso_缓冲区[16];
};
};
sizeof(void*)
=8的典型体系结构上,这使我们的总大小为32字节



1“三巨头”(GCC的libstdc++自第5版开始,Clang的libc++和MSVC的实现)都能做到这一点。其他的也可以。

std::string
通常包含一个用于“小字符串优化”的缓冲区——如果字符串小于缓冲区大小,则不需要堆分配。

它依赖于库。您不应该依赖于
std::string
对象的大小,因为它可能在不同的环境中发生变化(显然是在不同的标准库供应商之间,但也在同一库的不同版本之间)

请记住,
std::string
实现是由针对各种用例进行优化的人员编写的,通常会导致两种内部表示,一种用于短字符串(小内部缓冲区),另一种用于长字符串(堆分配的外部缓冲区)。开销与在每个
std::string
对象中保存这两个相关。

我的猜测是:

class vector
{
    char type;
    struct Heap
    {
      char*   start;
      char*   end;
      char*   allocatedEnd;
    };
    struct Stack
    {
      char    size;
      char    data[27];
    }
    union
    {
        Stack   stackVersion;
        Heap    heapVersion;
    } version;
};
但是我敢打赌有数百种方法可以做到这一点。

问:为什么狗是黄色的? 答:不一定

(一个?)std::string对象的大小取决于实现。我刚刚检查了微软VC++2010。它确实为std::string使用了32个字节。有一个16字节的联合,它包含字符串的文本(如果合适的话),或者一个指向较长字符串的堆存储的指针。如果实现者选择在string对象中而不是堆中保留18字节的字符串,那么大小将是34字节。其他16个字节包含开销,包含字符串长度和当前分配给字符串的内存量等内容

不同的实现可能总是从堆中分配内存。这样的实现无疑需要更少的字符串对象内存。

在g++5.2中(例如g++4.9中,它是不同的),字符串基本上定义为:

class string {
  char* bufferp;
  size_t length;
  union {
    char local_buffer[16];
    size_t capacity;
  };
};
在普通计算机上,这加起来是32字节(8+8+16)

当然,实际的定义是

typedef basic_string<char> string;
typedef基本字符串;

但是想法是一样的。

如果你打开平台的
标题,你可以确切地看到
std::string
为什么是这个大小@Queso:
sizeof
以字节为单位生成对象的大小。如果sizeof返回指针中的位数,则编译器将broken@Martin:因为“湿度”在很大程度上被定义为水(或液体)的特性。我不知道“32”被定义为字符串大小。@Steve Jessop:水是湿的,因为当前的实现(地球是一个STP,允许水是液体)。在其他实现中,它不是湿的(比如木星,它是一种气体)。所以这个字符串实现是32,因为这是它在这个实现中构建的方式,在其他实现中它将增加16,在另一个实现中增加64。管柱的大小(就像水一样)取决于它所处的环境。好的,因为地球的STP,水是液态的,我们可以通过观察影响它的因素(例如,大气压力受质量和气体排放的影响)进一步钻探。那么,问为什么一组实施者选择32,另一组选择64,与问为什么地球有一定的表面压力和温度有什么关系呢?一个是有知觉的生物做出的选择。另一个是IMO,但即使IYO,我也不认为C++实现者对上帝的不可操作性有相当的要求。Windows编译器并不是唯一进行小字符串优化的编译器当然,但如果您不愿意命名它们,那么很难判断这是“典型”行为,还是仅仅因为这是一个常见实现(可能还有其他实现)的行为而称之为“典型”行为。据我所知,Dinkumware和STLPort都是这样做的,但是gcc的实现没有。顺便说一句,我之所以提到它,是因为“通常”的范围从“我有理由相信你永远不会看到任何其他东西”到“我使用过的50%或更多的实现都可以做到这一点”。我认为这很容易被误解。无论是这种优化还是缺少优化,都不应被视为不寻常。@KonradRudolph非常小的字符串直接保存到对象中,这可以是堆栈,也可以是堆,具体取决于字符串本身的分配位置,否?@ManuelSelva正是如此。@KonradRudolph如何强制字符串始终为堆分配?(为了使字符串对象小于32字节,例如8字节。)@LukeFisk Lennon您不能。小字符串优化是某些(好吧,所有现代)标准库实现的一个实现细节,它不是由语言指定的。因此,你不能在C++中改变它。您也不能在C++之外改变它(例如通过编译器选项),因为这样的改变将是。也就是说,GCC4没有执行小字符串优化,因此原则上您可以使用
配置您的GCC——使用默认的libstdcxx abi=GCC4兼容