Why Does the Size of a Class Depends on the Order of the Member Declaration? and How

Why does the size of a class depends on the order of the member declaration? and How?

The reason behind above behavior is data structure alignment and padding. Basically if you are creating a 4 byte variable e.g. int, it will be aligned to a four byte boundary i.e. it will start from an address in memory, which is multiple of 4. Same applies to other data types. 2 byte short should start from even memory address and so on.

Hence if you have a 1 byte character declared before the int (assume 4 byte here), there will be 3 free bytes left in between. The common term used for them is 'padded'.

Data structure alignment

Another good pictorial explanation

Reason for alignment

Padding allows faster memory access i.e. for cpu, accessing memory areas that are aligned is faster e.g. reading a 4 byte aligned integer might take a single read call where as if an integer is located at a non aligned address range (say address 0x0002 - 0x0006), then it would take two memory reads to get this integer.

One way to force compiler to avoid alignment is (specific to gcc/g++) to use keyword 'packed' with the structure attribute. packed keyword Also the link specifies how to enforce alignment by a specific boundary of your choice (2, 4, 8 etc.) using the aligned keyword.

Best practice

It is always a good idea to structure your class/struct in a way that variables are already aligned with minimum padding. This reduces the size of the class overall plus it reduces the amount of work done by the compiler i.e. no rearrangement of structure. Also one should always access member variables by their names in the code, rather than trying to read a specific byte from structure assuming a value would be located at that byte.

Another useful SO question on performance advantage of alignment

For the sake of completion, following would still have a size of 8 bytes in your scenario (32 bit machine), but it won't get any better since full 8 bytes are now occupied, and there is no padding.

class temp
{
public:
int i;
short s;
char c;
char c2;
};

does order of members of objects of a class have any impact on performance?

Absolutely. C++ guarantees that the order of objects in memory is the same as the order of declaration, unless an access qualifier intervenes.

Objects which are directly adjacent are more likely to be on the same cacheline, so one memory access will fetch them both (or flush both from the cache). Cache effectiveness may also be improved as the proportion of useful data inside it may be higher. Simply put, spatial locality in your code translates to spatial locality for performance.

Also, as Jerry notes in the comments, order may affect the amount of padding. Sort the members by decreasing size, which is also by decreasing alignment (usually treat an array as just one element of its type, and a member struct as its most-aligned member). Unnecessary padding may increase the total size of the structure, leading to higher memory traffic.

C++03 §9/12:

Nonstatic data members of a
(non-union) class declared without an
intervening access-specifier are allocated so that later members have
higher addresses within a class
object. The order of allocation of
nonstatic data members separated by an
access-specifier is unspecified
(11.1). Implementation alignment
requirements might cause two
adjacent members not to be allocated
immediately after each other; so might
requirements for space for managing
virtual functions (10.3) and virtual
base classes (10.1).

What is the optimal order of members in a class?

As a rule of thumb you should order by size, greater to smaller. This will create the minimum padding of the structure, thus minimizing the structure size. This matters most if objects of the structure are used in a contiguous allocated memory, e.g. vector and helps a lot with cache (more objects fit in the same cache line).

Another surprising optimization demonstrated by Andrei Alexandrescu (I think was in one of CppCon) is that he brought the most accessed member first. This is faster because the offset is zero. Of course he was talking about micro-optimization, after benchmarking the hell out of the application and caring for every little strop of performance.

Does order of method declarations in a class matter to the compiler?

My question is whether it matters where in the list of public methods I add the new declaration

AFAIK, it does not matter if the member function is regular function but it matters if it is a virtual member function. The virtual member functions in the virtual table are in a certain order. If the library has them in a different order than your .h file, you'll most likely end up calling the wrong function.

Related: Force the order of functions in the virtual method table?

Why class size depend only on data members and not on member functions?

Because the class's functions are not saved inside the object itself. Think of it in terms of C programming, every function of class A takes one secret parameter, the this pointer, so in actuality they are just functions with one extra parameter.

For example imagine it like this:

int display(A* thisptr)
{
//do something
printf("%d",thisptr->a);
return;
}

So the display function is saved as just a simple function with one extra parameter. The name though is mangled depending on the compiler.

I believe that different rules apply for virtual functions which would involve function pointers but since I am not sure maybe someone else can enlighten us on this matter.

size of a user defined class

The compiler is free to insert padding in between and after class members in order to ensure that variables are properly aligned, etc. Exactly what padding is inserted is up to the implementation. In this case, I'd guess that the compiler is adding 3 bytes of padding after cl1::cb, perhaps to ensure that the next variable in memory is aligned on a 4-byte boundary.

c++ initialize class member variable depends on other member variable

Your specific issue is due to the fact that variable length arrays are not supported in C++. Consider using a std::vector or another C++ standard library container instead.

But you have further problems (which in my opinion makes your question interesting): the order of member initialisation is the order they appear in the class definition, not the order they appear in the initialisation.

For example, in your case theta is initialised before detected_range, and since the latter is not initialised at the point you use it in the evaluation of theta, the behaviour of your code is undefined!

In your case, unless you need the members to be const, I'd initialise the ones that are not set to literals in the constructor body if I were you.

Fixing order of inclusion when there is circular dependency in C++ template classes

I need Bar to be included before Foo, no matter in what order they're included in main.cpp. The following hack seems to work:

In Foo.h, include Bar.h outside the header guards. As Bar has header guards too, it does not get included multiple times.

Foo.h

#include"Bar.h"

#ifndef FOO_H
#define FOO_H

class Foo
{
public:
Bar<> B;
void fooStuff(){};

};
#endif

Bar.h

#ifndef BAR_H
#define BAR_H

class Foo;
template<int N=0> class Bar
{
public:
Foo * F;
void barStuff();
};

#include"Foo.h"
template<int N> void Bar<N>::barStuff()
{
F->fooStuff();
};
#endif

main.cpp

#include"Foo.h"
#include"Bar.h"
int main()
{
Foo F;
F.B.barStuff();
};


Related Topics



Leave a reply



Submit