简体   繁体   中英

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

When I write the following code:

#include <iostream>

struct gg
{
   gg() {}
   int a, b, c;
};

int main()
{   
    std::cout << sizeof(gg()) << std::endl;
}

the result is 1 .

But when I use a non-default constructor, like so:

#include <iostream>

struct gg
{
   gg(int x) {}
   int a, b, c;
};

int main()
{   
    std::cout << sizeof(gg(10)) << std::endl;
}

the output is 12.

Since both examples have the same data members in gg , I expect them both to result in the same output.

Why did sizeof(gg()) result in 1 ?

There are two versions of sizeof . One expects a unary-expression , and the other expects a parenthesized type-id . The first version leaves its operand unevaluated. The following is perfectly legal and outputs 12 :

std::cout << sizeof gg();

On the other hand, sizeof(gg()) is illegal. It's trying to apply sizeof to a function type. 1 The second code snippet is legal and has expected behavior.

§5.3.3:

1 ... The sizeof operator shall not be applied to an expression that has function or incomplete type, ...

3 The sizeof operator can be applied to a pointer to a function, but shall not be applied directly to a function.

4 The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are not applied to the operand of sizeof .

The first code snippet fails in Clang ( live example ), and is documented as an extension in the GCC manual :

6.23 Arithmetic on void- and Function-Pointers

In GNU C, addition and subtraction operations are supported on pointers to void and on pointers to functions. This is done by treating the size of a void or of a function as 1.

A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.

The option -Wpointer-arith requests a warning if these extensions are used.

(emphasis mine)

It appears that this extension exists in C++ mode as well, considering that I receive a warning . In order to reject this code, use -Wpedantic-errors . For the code snippet which fails, simply use sizeof(gg) or sizeof(gg{}) . The latter and sizeof gg() are needless obfuscation and sizeof gg is illegal since parentheses are required around the typename.


Footnote

  1. Some are suggesting that this is the most vexing parse . To strengthen the argument, consider that Clang will reject any function type, sizeof(int(int, char)) , sizeof(gg(int, char)) , what have you. On the other hand, sizeof int(45) returns 4 and sizeof gg(45) (for where gg has a converting constructor) returns 12, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM