为什么采用使用默认构造函数构造的对象的“sizeof”总是导致 1

Why does taking the `sizeof` of an object constructed with a default constructor always result in 1?

本文关键字:sizeof 对象 默认 构造函数 为什么      更新时间:2023-10-16

当我编写以下代码时:

#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是非法的,因为类型名称周围需要括号。

<小时 />

脚注

  1. 有些人认为这是最令人烦恼的解析。为了加强论证,请考虑 Clang 将拒绝任何函数类型,sizeof(int(int, char))sizeof(gg(int, char)),你有什么。另一方面,sizeof int(45) 返回 4sizeof gg(45)(对于gg具有转换构造函数的地方(返回 12,依此类推。