如何 sizeof(std::cout) 是 140 而 sizeof(std::string) 只有 4?

How sizeof(std::cout) is 140 whereas sizeof(std::string) is only 4?

考虑以下程序:

#include <iostream>
int main()
{
    std::cout<<sizeof(std::string)<<'\n';
    std::cout<<sizeof(std::ostream)<<'\n';
    std::cout<<sizeof(std::istream)<<'\n';
    std::cout<<sizeof(std::cout);
}

我的编译器 (g++ 4.8.1) 的输出是

4

140

144

140

输出结果让我很困惑。为什么 sizeof string class 只有 4 个字节,对于 ostream 和 istream 它分别给出 140 和 144 个字节? sizeof(std::cout) 是 140 个字节,与 sizeof(std::ostream) 相同。所以,我认为因为 cout 对象是 ostream 类型,所以我在这里得到相同的输出。正确的?这些大小是否依赖于编译器?

基本上归结为 iostream 有相当多的状态要存储,而字符串却很少。

尽管如此,字符串的大小仅为 4 的想法有点令人惊讶(至少对我而言)。我通常期望 32 位实现为 12,64 位版本为 24。

特别是,一个字符串通常包含三样东西:一个指向用于保存数据的实际缓冲区的指针(通常分配在空闲存储上),一个 size_t 用于包含该缓冲区的大小,以及a size_t 包含当前存储的字符数。在典型情况下,每一个在 32 位实现上都是 32 位,在 64 位实现上都是 64 位。

完全有可能证明一个比它大一些的字符串对象也是合理的——例如,将一个小字符串的数据直接存储在字符串对象本身中是相当常见的 ("short string optimization")。在这种情况下,您可能 space 用于(最多)字符串对象本身中的 20 个字符,这通常会进一步增加其大小。