大小为0的对象

Pri*_*iJC 5 c++

我知道C++中的空类大小为1个字节.但是,我注意到sizeof()为此类的对象返回0(以g ++为单位):

    class Boom{
        int n[0];
    }
Run Code Online (Sandbox Code Playgroud)

我可以为Boom对象打印有效的内存位置:

    Boom b;
    cout<<&b;
Run Code Online (Sandbox Code Playgroud)

这个特定的内存位置是否占用?如果我稍后在程序中分配内存,是否有可能使用此位置?

Mik*_*our 8

数组的大小不能为零.如果您的编译器允许您声明一个,那么该语言不会指定它的行为方式.

在这种情况下,使用此编译器,确实看起来这允许两个对象占据相同的位置:

Boom b[2];
std::cout << &b[0] << ' ' << &b[1] << std::endl;

// Output: 0x7fffffb23fdc 0x7fffffb23fdc
Run Code Online (Sandbox Code Playgroud)

但是其他编译器可能表现不同,或者只是拒绝无效声明(如果你指定GCC会这样做-pedantic -Werror).

  • 有趣的是,即使sizeof(b)在那里也是0 (2认同)

Seb*_*ach 5

代码无效.

对于类和数组,大小为0都是无效的.C++标准说:

Sizeof [expr.sizeof]

[...]最派生类的大小应大于零[...]

数组[dcl.array]

在TD的声明中,D表格

    D1 [ constant-expressionopt] attribute-specifier-seqopt
Run Code Online (Sandbox Code Playgroud)

[...]如果存在常量表达式(5.19),它应该是一个整数常量表达式,其值应大于零[...]


为什么编译?编译器扩展!

如果您-pedantic使用g ++ 打开,您将收到以下警告(或错误pedantic-errors):

ISO C++ forbids zero-size array ‘n’
Run Code Online (Sandbox Code Playgroud)

因此,您的程序基本上无效,但可以通过C++标准的编译器扩展进行编译(除非您关闭此扩展).

注意:即使你的编译器可以报告0class,也不会为任何实例(又名对象)这样做class:

#include <iostream>
class Boom {
    int n[0];
};
int main() {
    std::cout << sizeof(Boom) << '\n';   // prints 0
    std::cout << sizeof(Boom()) << '\n'; // prints 1
}
Run Code Online (Sandbox Code Playgroud)

具有大小为0的对象将远离标准.

引用Stroustroup:

为什么空类的大小不为零?

确保两个不同对象的地址不同.出于同样的原因,"new"总是返回指向不同对象的指针.考虑:

class Empty { };

  void f()
  {
      Empty a, b;
      if (&a == &b) cout << "impossible: report error to compiler supplier";
      Empty* p1 = new Empty;
      Empty* p2 = new Empty;
      if (p1 == p2) cout << "impossible: report error to compiler supplier";
  } 
Run Code Online (Sandbox Code Playgroud)

有一条有趣的规则表明空基类不需要用单独的字节表示:

   struct X : Empty {
        int a;
        // ...
   };

   void f(X* p)
   {
       void* p1 = p;
       void* p2 = &p->a;
       if (p1 == p2) cout << "nice: good optimizer";
   }
Run Code Online (Sandbox Code Playgroud)

这种优化是安全的,并且是最有用的.它允许程序员使用空类来表示非常简单的概念而不会产生开销.一些当前的编译器提供了这种"空基类优化".

  • 这并不能解释为什么`sizeof`为`Boom`报告'0`?http://ideone.com/sYvosz (3认同)