23

I have a C++ question. I wrote the following class:

class c
{
    int f(int x, int y){ return x; }
};

the sizeof() of class c returns "1". I I really don't understand why it returns 1.

Trying to understand better what is going on, I added another function:

class c
{
     int f(int x, int y){ return x; }
     int g(int x, int y){ return x; }
};

Now the following really got me confused! sizeof(c) is still 1 (!?!?!?!). So I guess that functions doesn't change the size of the class, but why??? and why does the size is 1 ? And is it compiler specific ?

Thanks! :-)

TCS
  • 5,790
  • 5
  • 54
  • 86

7 Answers7

49

The class contains no data members, so it's empty. The standard demands that every class have at least size 1, so that's what you get. (Member functions aren't physically "inside" a class, they're really just free functions with a hidden argument and a namespace and access control.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    Technically, the standard says everything must have an address. (If the size couldn't be zero the empty base optimization wouldn't work) – Billy ONeal Jul 01 '11 at 19:19
  • @Billy But it makes it less problematic for people who insist on doing stupid things like `malloc(sizeof(classname) * num_classes)` – Chris Eberle Jul 01 '11 at 19:21
  • Learn something new all the time. Question: Do virtual functions take space on a per-object basis and therefore increase the sizeof an object? – SirPentor Jul 01 '11 at 19:32
  • @Tobias: Whether or not you have a vtable matters (I think 4 bytes on x86?), so there's a difference whether you have any or no virtual functions. – Kerrek SB Jul 01 '11 at 19:33
  • 1
    @Tobias: Generally, no. The addition of a virtual function will increase the size of your object by the size of a pointer that points to the list of all virtual functions used by the type. Extra virtual functions increase the size of that list, but you still only have to carry around the one pointer on a per-object basis. None of this is mandated by the standard, of course. – Dennis Zickefoose Jul 01 '11 at 19:35
  • The point is, if I'm using `sizeof` in some calculation and `sizeof` returns 0, I may not be expecting this behavior and things go awry. If I use `sizeof` multiplied by some constant within the context of `malloc`, if `sizeof` returns `0`, then malloc will allocate nothing, which is unexpected. In other words, it may just be the developers attempting to fix corner cases like this. – Chris Eberle Jul 01 '11 at 20:09
  • @Tobias: The compiler createas a vtable for each class that has one virtual function. There's only one vtable per class, not per object: http://stackoverflow.com/questions/1626290/c-virtual-function-table-memory-cost – Gnawme Jul 01 '11 at 20:30
  • 3
    @Chris: `sizeof` can never return 0. The smallest addressable unit on a machine is defined to be `char`, and that is defined to be `1`. For everything to have an address it must be addressable. The only difference between the wording "everything must have an address" and "everything must have nonzero size" is the empty base optimization, which is not going to affect use of `sizeof`. – Billy ONeal Jul 01 '11 at 21:31
  • @Billy: I'm so damn confused. Just above you said that the size *could* be zero to support the empty base optimization. That's why I was arguing in the first place. – Chris Eberle Jul 01 '11 at 21:40
  • 1
    @Chris: The standard says everything has to be addressable. Compilers can optimize such that the base class and derived class have the same address though. `sizeof` will still always return at least 1, even though the base class *effectively* has no size (it shares the address with the derived class instance). See: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=319 – Billy ONeal Jul 01 '11 at 21:55
  • 1
    Think of it this way: the size of an object is calculated by adding together its storage requirements, including those of its base classes and virtual method table pointers. If the calculated size is 0, it is rounded up to 1, as a *final* step in calculating size. I.e. This rounding does not occur after calculating a base's size before adding any additional storage needs of the derived class. This guarantees that `operator new(size_t size)` is not called with `size == 0`. The case of `malloc(sizeof(classname) * num_objects)` is sometimes found in the implementation of `operator new[]()`. – Mike DeSimone Jul 02 '11 at 02:30
  • @Chris why is `malloc(sizeof(classname) * num_classes)` "stupid" ? – johnbakers Apr 12 '13 at 02:08
12

It's size is of 1, because it can not be 0, otherwise two objects of this type wouldn't be addressable (couldn't differentiate their addresses)

BЈовић
  • 62,405
  • 41
  • 173
  • 273
7

Member functions are, essentially, the same as regular functions, they just get a hidden this paramter. So each instance of a given type does not need to carry around copies of its member functions; the compiler just keeps track of the regular functions, and provides an appropriate this paramter for you. So no matter how many functions a given type has, there is no need for its size to change. When you get into complicated inheritance with virtual functions and whatnot, this changes slightly, but in the end the number of functions continues to have no impact on the final size of the object.

The initial size of one byte is because all objects have to occupy some space, so that you can be guarenteed no two objects occupy the same space. Consider an array... a[5] is the same as *(a + 5), and adding to a pointer increases the memory address by the size of the object. if sizeof(a) were 0, then all the elements of the array would collapse down to the same address.

That the objects type of some space is mandated by the standard... that the size be equal to exactly one is not. sizeof(c) in your case could be 23, but there's no reason for it.

For completeness, it is possible for a sub-object to have a size of zero. The empty base optimization allows for a base class to not occupy any actual memory if it does not need to. So sizeof(Base) == sizeof(Derived) might be true, even though formally Derived contains an instance of Base hidden inside it. This is allowed by the standard, but not mandated by it... MSVC, for instance, does not make use of it in some situations.

Dennis Zickefoose
  • 10,791
  • 3
  • 29
  • 38
1

1 means 1 byte. And the reson is that methods are not stored within an object. They are used by objects, but not stored in them. Only class members are stored in objects. Try to add a plain int member or something and see what happens.

Chris Eberle
  • 47,994
  • 12
  • 82
  • 119
  • To be more precise, 1 means 1 * sizeof( char ), which is 1 byte at most implementations – Grigor Gevorgyan Jul 01 '11 at 19:19
  • 1
    @Grigor: `sizeof(char)==1` always, because a char is a byte and sizeof returns a number of bytes. (However, a byte is not necessarily exactly eight bits.) – aschepler Jul 01 '11 at 19:23
  • 1
    @Grigor: No, 1 means one byte. `sizeof(char)` is guarenteed to be 1 by the standard, not by the implementation. – Dennis Zickefoose Jul 01 '11 at 19:23
  • Everything I've read indicates that `sizeof` returns the number bytes, not some multiple of the size of a char (which may not necessarily be one byte). – Chris Eberle Jul 01 '11 at 19:24
  • 2
    @Chris: It depends on your definition of `byte`. The C++ standard defines one byte to be the size of one `char`... if you define one byte to be eight bits, then you are using a different definition. On a platform with sixteen bit `char` values, one byte will be sixteen bits. – Dennis Zickefoose Jul 01 '11 at 19:31
  • 1
    B.Stroustrup, C++ programming language, 3rd edition. Section 4.6. Quote: "Sizes of C++ objects are expressed in terms of multiples of the size of a *char* , so by definition the size of a *char* is 1 ." – Grigor Gevorgyan Jul 01 '11 at 19:34
  • 2
    The C++ standard: "The sizeof operator yields the number of bytes in the object representation of its operand." As influential as the good Mr Stroustrup is, the standard is more authorative. – Dennis Zickefoose Jul 01 '11 at 19:47
  • @Dennis My personal definition of a byte is about 2 oz of tender chicken. However this isn't about my personal beliefs. – Chris Eberle Jul 01 '11 at 19:53
  • @Dennis: Yes, just checked that.. such a mismatch is a bit strange though – Grigor Gevorgyan Jul 01 '11 at 19:54
  • I really shouldn't be on here during my lunch break. The chicken was mighty tasty though. – Chris Eberle Jul 01 '11 at 19:56
  • 1
    @Grigor: From: n3242: Section 5.3.3 [expr.sizeof] paragraph 1: **The sizeof operator yields the number of bytes in the object representation of its operand.** – Martin York Jul 01 '11 at 20:15
  • @Martin: thank you, somewhere in my chicken-filled gut I knew I heard that somewhere. – Chris Eberle Jul 01 '11 at 20:17
  • Both statements are true, kids today just never saw computers with bigger bytes. `sizeof(char)` is guaranteed to be 1, because a char is one byte. "Byte" is synonymous with "smallest size", not "eight bits". –  Jul 02 '11 at 07:11
0

sizeof(char)==1 always, because a char is a byte and sizeof returns a number of bytes. (However, a byte is not necessarily exactly eight bits.)

Absolutely true. Hence the term "octet" (to distinguish something that is exactly 8 bits from the more commonly used term "byte").

For more info, look at IEEE 1541:

http://en.wikipedia.org/wiki/IEEE_1541

paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • What does sizeof(char) have to do with the question? – user207421 Jul 04 '11 at 01:17
  • If you'd look above, "sizeof(char)" came up in the above discussion. So I tried to reply. I've taken a lot of heat over this stupid discussion, but the OP asked a legitimate question, I tried to give a legitimate answer ... but there are just too many people responding who've drunk the C++ Kool-Aide. Kerrek SB clearly gave the best answer: a C++ "class" HAS NO "size", but the C++ standard (arbitrarily) says "sizeof()" can't return "0" - hence it returns the (nonsensical) result of "1". I cited IEEE 1541 in response to Chris, AShepler, et al – paulsm4 Jul 04 '11 at 01:32
-1

Q: Do virtual functions take space on a per-object basis and therefore increase the sizeof an object?

A: No. The more virtual functions, the larger the vtable. The the more subclasses, the more vtables. If a class has no virtual functions, then there's no need for either a vtable or a (per-object) vtable pointer.

But none of this affects "sizeof". The functions themselves take a fixed amount of space, regardless.

paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • 2
    Isn't there only one vtable per _class_, rather than one per instance (with one pointer to vtable per instance)? – snarf Jul 02 '11 at 02:33
  • That is wrong. If the number of `virtual` method is `> 0`, the `vtable` object size remains constant. If there is no `virtual` method then object size will be 1 function pointer less. – iammilind Jul 02 '11 at 04:20
  • 1
    No, *that* is wrong. You are confusing the vtable, which has an entry per virtual function, with the vtable pointer, which is always the same size unless it is absent as in this case because there are no virtual functions ... in which case there is no vtable either. – user207421 Jul 04 '11 at 01:18
-4

Because your class is a "reference variable" and, per MSDN: "The sizeof operator never yields 0 even for an empty class."

EXAMPLE:

#include <stdio.h>

class c { public: int f(int x, int y){ return x; } int g(int x, int y){ return x; } };

struct s { int f; int g; };

int main (int argc, char *argv[]) { c objc; s objs; printf ("sizeof (c)= %d, sizeof (objc)= %d, sizeof (class c)= %d...\n", sizeof (c), sizeof (objc), sizeof (class c)); printf ("sizeof (s)= %d, sizeof (objs)= %d, sizeof (struct s)= %d...\n", sizeof (s), sizeof (objs), sizeof (struct s)); return 0; }

RESULT:

sizeof (c)= 1, sizeof (objc)= 1, sizeof (class c)= 1...
sizeof (s)= 8, sizeof (objs)= 8, sizeof (struct s)= 8...

Note, too, the difference between "struct" and "class".

Here's more info:

http://www.geekinterview.com/question_details/42847

paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • 3
    A class is not a "reference variable". sizeof acts the same for both classes and structs, so what I think you're trying to demonstrate with your code is invalid. This isn't C#. This is the real output of your sample code, after adding in the missing %d: sizeof (c)=1, sizeof (objc)=1, sizeof (s)=8, sizeof (objs)=8 – Darryl Jul 01 '11 at 21:54
  • Look, I'll grant you that the term "reference variable" doesn't exist in C++ ... but the C# term is analogous to C++. So don't bust my chops, OK ;)? The fact is, classes are "special". Which I believe the code snippet clearly shows. Strictly speaking, the size is "0". But, per the C++ standard: "Complete objects and member subobjects of class type shall have nonzero size." Hence "1". – paulsm4 Jul 02 '11 at 02:15
  • 1
    Structures and classes in C++ are basically the same, except that members of classes are private by default and members of structures are public. You are using methods in your example class but variables in your structure - of course there's gonna be a difference between them. – Frxstrem Jul 02 '11 at 02:32
  • Frxstrem - Stroustrup explicitly says "structs and classes" are the same, except that the latter's members are private by default, and the formers are public by default. This might technically be "correct". But, the fact is, "structs" in C++ can and do have *significant* differences than their counterparts in C. Especially if you throw in stuff like constructors and private members. – paulsm4 Jul 02 '11 at 05:36
  • 2
    I can't see the point of this discussion. A C++ class is not a reference variable. If Stroustrup says something about C++, you can bet that it is technically correct, but the differences between classes and structs are immaterial to the OP's question, unless you are claiming that sizeof (struct) can be zero. Are you? – user207421 Jul 04 '11 at 01:24