我们都知道空类的大小或空类的对象将是1个字节。
我遇到了sizeof
一个类及其对象变为0的东西。该程序在语法上是正确的,因为没有编译或运行时错误。这是未定义的行为吗?我试图执行的用例有意义,看起来像一个有效的用例?不给类中的数组提供精确的下标或大小是一个很大的错误吗?代码段如下:
#include<iostream>
using namespace std;
class A
{
char a[];
};
int main()
{
A b;
cout<<sizeof(A)<<endl;
cout<<sizeof(b)<<endl;
return 0;
}
输出:
0
0
sizeof
一个空类是一个字节(基本上不为零),其原因就像&#34;确保不同的对象具有不同的地址&#34;。
在这种情况下,当sizeof
班级为零时会发生什么?
注意:同样观察int a[]
的行为。
答案 0 :(得分:25)
它被称为“灵活的数组成员”,它是C99的一个功能(我认为)。它不是有效的C ++ - 你没有警告/错误,可能是因为编译器支持它作为扩展。
使用-Wall -Wextra -pedantic -std=c++NN
(98,03,11,14,..)进行编译应生成警告(最后两个标志将禁用任何编译器扩展)。
您可以在此相关问题中查看一些信息:Is using flexible array members in C bad practice?
例如,以下是GCC对此的说法:
在ISO C99中,您将使用灵活的数组成员,其语法和语义略有不同:
...
灵活的数组成员具有不完整的类型,因此可能不会应用sizeof运算符。 作为零长度数组原始实现的一个怪癖,sizeof的计算结果为零。
(来源:https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html)。
这解释了0
char a[]
的大小,而不是类的0,但正如我已经提到的那样 - 它是一个C功能,而不是一个有效的C ++。
答案 1 :(得分:6)
如果使用-pedantic
标志进行编译
$ g ++ -W -Wall -pedantic prog.cpp
prog.cpp:5:11:警告:ISO C ++ 禁止零大小的数组'a'[-pedantic]
C ++不支持undefined behaviour,因此您的类声明不合法,超出了标准C ++规则的范围。
答案 2 :(得分:1)
你的代码不是标准的C ++,因此我看不出任何意义。
如果你使用迂腐旗帜,你应该收到:
gsamaras@pythagoras:~$ g++ -pedantic file.cpp
file.cpp:5:11: warning: ISO C++ forbids zero-size array ‘a’ [-Wpedantic]
char a[];
^
尝试将课程更改为
class A {
char a[5];
};
然后你应该得到
的输出5
5
就像你应该期待的那样。
但是,您可以争辩说,如果没有标志,您的代码会编译并输出零。作为一个计数器,我可以说如果你使用这个类也一样:
class A {
char a[0];
};
但是我很确定你知道不允许零大小的数组,但是这个东西编译得很好并且输出为零。
答案 3 :(得分:-1)
空基类可以优化为零字节,从技术上讲,sizeof(base)
也可以0
。
&#34; 1字节&#34;事实上是一个实现细节,来自不同对象需要具有不同地址的规则。
所以:
struct base { };
struct derived : base { };
sizeof(base)
和sizeof(derived)
都允许0
,因为derived
对象与其中包含的base
对象是同一个对象。
然而:
struct base1 { };
struct base2 { };
struct derived : base1, base2 { };
此处,sizeof(derived)
必须为1,因为标准要求
derived d;
assert(static_cast<base1 *>(&d) != static_cast<base2 *>(&d));
类似地:
struct type1 { };
struct type2 { };
struct combined { type1 obj1; type2 obj2; };
要求
combined c;
assert(&c.obj1 != &c.obj2);
许多编译器供应商采用快捷方式,只需使空类占用一个字节。
答案 4 :(得分:-1)
类的大小可以是0.考虑以下代码
#include <iostream>
using namespace std;
class A
{
public:
int a[0];
void getA(){
cout<<"Hello World";
}
};
class B
{
};
int main()
{
cout<<"The size of A is "<<sizeof(A)<<endl; // prints 0
A w;
cout<<"The size of object of A is "<<sizeof(w)<<endl; //prints 0
cout<<"The size of the array a in A is "<<sizeof(w.a)<<endl; // prints 0
cout<<"The value from function of class A is "<<w.getA()<<endl; // Gives a compilation error
cout<<"The size of B is "<<sizeof(B)<<endl; //prints 1
}
Output:
The size of A is 0
The size of object of A is 0
The size of the array a in A is 0
The size of B is 1
因此,访问类中存在的大小为0的函数会导致编译错误。