为什么采用使用默认构造函数构造的对象的“sizeof”总是导致 1
Why does taking the `sizeof` of an object constructed with a default constructor always result in 1?
当我编写以下代码时:
#include <iostream>
struct gg
{
gg() {}
int a, b, c;
};
int main()
{
std::cout << sizeof(gg()) << std::endl;
}
结果是 1
.
但是当我使用非默认构造函数时,如下所示:
#include <iostream>
struct gg
{
gg(int x) {}
int a, b, c;
};
int main()
{
std::cout << sizeof(gg(10)) << std::endl;
}
输出为 12。
由于两个示例在gg
中具有相同的数据成员,我希望它们都产生相同的输出。
为什么sizeof(gg())
导致1
?
sizeof
有两个版本。一个需要一元表达式,另一个需要括号中的类型 ID。 第一个版本不计算其操作数。以下内容是完全合法的,输出12
:
std::cout << sizeof gg();
另一方面,sizeof(gg())
是非法的。它试图将sizeof
应用于函数类型。1 第二个代码段是合法的,并且具有预期的行为。
§5.3.3:
1
......sizeof
运算符不得应用于表达式 具有功能或不完整的类型,...
3
sizeof
运算符可以应用于指向函数的指针, 但不得直接应用于函数。
4
左值到右值 (4.1(、数组到指针 (4.2( 和函数到指针 (4.3( 标准转换不适用于sizeof
的操作数。
第一个代码片段在 Clang 中失败(实时示例(,并作为扩展记录在 GCC 手册中:
6.23 空指针和函数指针的算术
在 GNU C 中,加法和减法运算在 指向 void 的指针和指向函数的指针。这是由 将空隙或函数的大小视为 1。
这样做的结果是,在 void 和函数类型上也允许 sizeof,并返回 1。
选项 -Wpointer-arith 请求警告,如果这些扩展是 使用。
(强调我的(
考虑到我收到警告,此扩展似乎也存在于C++模式下。要拒绝此代码,请使用 -Wpedantic-errors
。对于失败的代码片段,只需使用 sizeof(gg)
或 sizeof(gg{})
。后者和sizeof gg()
是不必要的混淆,sizeof gg
是非法的,因为类型名称周围需要括号。
脚注
- 有些人认为这是最令人烦恼的解析。为了加强论证,请考虑 Clang 将拒绝任何函数类型,
sizeof(int(int, char))
、sizeof(gg(int, char))
,你有什么。另一方面,sizeof int(45)
返回4
和sizeof gg(45)
(对于gg
具有转换构造函数的地方(返回 12,依此类推。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 同一对象的"sizeof"的不同答案
- 对象的大小,而不在C++中使用 sizeof
- Sizeof 舍入到对齐方式,但编译器仍将对象放在剩余的字节中
- 只有当声明一个对象时,内存空间才会分配给类的数据成员,那么为什么 Sizeof(class_name) 给我结果
- 为什么采用使用默认构造函数构造的对象的“sizeof”总是导致 1
- 使用 Sizeof、malloc 和 cast 的 C++ 对象实例化
- 当我们对没有任何数据成员的类的对象使用sizeof运算符时.那么输出会是什么
- 对象表示形式的定义和运算符sizeof
- sizeof操作符是否优先选择对象而不是类型
- sizeof(指针)依赖于对象类型吗?