【问题标题】:what is sizeof() operator doing in C++C++ 中的 sizeof() 运算符在做什么
【发布时间】:2014-09-16 12:00:53
【问题描述】:

C 中的sizeof() 运算符在编译时给出其操作数的大小。它不评估其操作数。例如,

int ar1[10];
sizeof(ar1) // output 40=10*4
sizeof(ar1[-1]) // output 4
int ar2[ sizeof(ar1) ]; // generate an array of 40 ints.

当谈到 C++ 模板类时,我发现了一些奇怪的结果。

template<typename T>
struct S{
    T a;
};

sizeof( S<int> )       // output 4
sizeof( S<bool> )      // output 1
sizeof( vector<int> )  // output 24
sizeof( vector<char> ) // output 24
sizeof( vector<bool> ) // output 40

我猜向量或其他 STL 容器上的 sizeof 取决于特定环境。

问题1.sizeof在C/C++中是如何实现的?它不能是运行时函数。是宏吗? (我在在线教程视频中学到的)。如果是宏,它的#define 是什么样的? sizeof()什么时候执行?

问题2。如果我在struct S的定义中添加一个成员方法void f(){}sizeof(S&lt;int&gt;) 还是 4,不应该增加 struct 的大小吗?

问题 3。 STL 容器是模板类。以vector 为例,它有12 个成员属性/类型和许多成员方法? sizeof( S&lt;int&gt; ) 的输出很容易解释。但我发现很难解释sizeof( vector&lt;int&gt; ) 的输出。模板类应在编译时实例化,编译器应完全了解类的大小,即vector&lt;int&gt;sizeof()运营商应该知道。

【问题讨论】:

  • 你一次问了太多问题。问题 2 在这里回答:stackoverflow.com/questions/8058213/…
  • sizeof 是 C/C++ 中的关键字。我还没有看到宏的名称成为关键字。也许 sizeof 不是宏。
  • @Slava 谢谢。老实说,我不会在我的代码中以那些奇怪的方式使用 sizeof。只是觉得对 sizeof 的行为太无知了。
  • 哪个视频说sizeof是宏?
  • @chris 在edu.51cto.com/lesson/id-30061.html的中文视频中有解释

标签: c++ stl sizeof


【解决方案1】:

根据问题 1sizeof 由编译器实现和评估。它不是宏,它总是提供编译时结果。从概念上讲,您可以想象编译器将每个sizeof 替换为一个数字。

根据问题2sizeof 计算S 的一个实例占用的存储量。一个方法不采用每个实例的存储,只有字段这样做(因为它们每个实例存在一次)。但是,方法确实会占用静态存储空间来保存函数的机器代码。

根据问题 3:对于 sizeof(vector&lt;int&gt;),编译器会计算 vector&lt;int&gt; 的大小,并为此对其进行实例化。如果您因为 vector 的大小可变而感到困惑:这是真的,但额外的存储空间是从堆中分配的,因此不会反映在 sizeof 应用于 vector 的结果中。

【讨论】:

  • Q2 除非它是第一个将添加一些存储的虚拟功能,此问题已在此处回答 stackoverflow.com/questions/8058213/…
  • std::vector&lt;bool&gt; 是一个显式调用的特化,它可能使用比法线向量更多的空间。
  • @PengZhang vector&lt;bool&gt; 这是一个非常奇怪的数据结构,它基本上是标准 C++ 库中规则的少数例外之一;跳过它。
  • @PengZhang,这些是类型别名。它们不占用每个实例的空间。
  • @PengZhang, typedef. #define 做不到(可靠地)。这远远超出了 C++ STL。关键是你可以说vector&lt;int&gt;::size_type 来获得例如size() 返回的类型。数据成员的实际数量取决于实现。
【解决方案2】:
  1. sizeof 不是宏。它是一个内置运算符并产生一个常量表达式,因此您可以想象编译器只是在编译时将其替换为一个字面量,该字面量的值是对象或类操作数的大小。

  2. 函数不会占用对象内部的空间。函数的代码不存储在对象内部。

  3. std::vector&lt;int&gt; 等容器的大小是向量成员占用的内存量,加上一些实现定义的填充。它不包括向量通过持有指针“拥有”的任何内存。 (请注意,向量的元素是 not 成员——当我说成员时,我的意思是在 std::vector 类的定义中声明的成员。)因此它与内部有多少元素无关向量。

【讨论】:

  • 函数不占用对象内部的空间。该函数的代码不存储在对象内 - 好吧,我只是好奇。我相信一个对象仍然必须持有一个指向其函数的指针,如果它是真的,那么这个指针会占用几个字节的内存,不是吗?
  • @AndreyChernukha 不。如果函数不是虚拟的,那么编译器可以在编译时确定它的地址;调用成员函数不需要检查对象。如果函数是虚函数,则通常只有一个 single 指针添加到对象,该指针指向存储在其他地方的表,该表给出对象的 all 虚函数的地址类。
  • 非常感谢您的回答。很难选择另一个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-29
  • 2011-12-11
  • 1970-01-01
  • 2016-03-29
  • 1970-01-01
相关资源
最近更新 更多