This question already has answers here:
Where are member functions stored for an object?
(2 answers)
Closed 6 years ago.
Whenever object is created for a class, memory space will be allocated for a class. So my question is: Do memory created for only member variables or for member functions also?? If memory is created for member functions, then where they will be stored??
Traditionally executable files had three sections. One for initialized data, one for uninitialized data, and one for code. This traditional partitioning is still very much in use, and code, no matter where it comes from, is placed in a separate section.
When an operating system load an executable file into memory, it puts the code in a separate place in memory that it marks as executable (on modern memory-protected systems) and all code are stored there separate from the objects themselves.
Member functions are just code located in the code segment. they are present exact one time, no matter how many objects you have.
They are nearly exactly the same as ordinary functions except that their first parameter is the this pointer, that is hidden in the language but present as a parameter on the executable code.
But there are two kinds of member functions:
"normal"
virtual
there is no difference between them in the sense of code size however they are called differently. Calls to normal functions can be determined by compiletime and the other are indirect calls via the function pointers-
If a class has a virtual member functions (the class is "polymorph") the compiler needs to create a "vtable" for this class (not object).
Each object does contain a pointer to the vtable of its class. this is necessary to access the correct virtual function if the object is accessed by a pointer that is of a base classes type.
Example:
class A{
public: bool doSomething();
int i;
};
class B:public A {
public: bool doSomething();
int j;
}
//
B b;
A* a = &b;
a->doSomething(); // <- A::doSomething() is called;
//
neither of this classes needs a vtable.
Example 2:
class A{
public: virtual bool doSomething();
int i;
};
class B:public A {
public: bool doSomething();
int j;
}
//
B b;
A* a = &b;
a->doSomething(); // <- B::doSomething() is called;
//
A (and all its childs) get a vtable. Then an object is created the objects vtable pointer is set to the correct table, so that independently from the Type of the pointer the correct function is called.
Only the member variables (plus padding between and after them) contribute to the sizeof of a class.
So in that sense regular functions do not take up space as far as an object is concerned. Member functions are little more than regular static functions with a implicit this pointer as a hidden argument.
Saying that though, a virtual function table might be the way an implemention deals with polymorphic types, and that will take up some space, but will probably only be a pointer to a table used by all objects of that particular class.
Related
Here is a simple C++ class, named A:
class A
{
public:
explicit A() : m_a(0) { }
explicit A(int a) m_a(a) { }
int getA() const { return m_a; }
void setA(int a) { m_a = a; }
private:
int m_a;
}
This is what I know so far:
When you declare an object of a class instance, memory gets allocated for that object. The allocated memory is equivalent to the memory of its members summed up. So in my case, it is:sizeof(A) = sizeof(int) = sizeof(m_a)
All member functions of class A are stored somewhere in memory and all instances of class A use the same member functions.
This is what I don't know:
Where are member functions stored and how are they actually stored? Let's say that an int for example is stored on 4 bytes; I can imagine the RAM memory layout with 4 contiguous cells each storing a part of that int. How can I imagine this layout for a function?(this could sound silly, but I imagine functions must have a place in memory because you can have a pointer point to them). Also how and where are function instructions stored? My first perception was that functions and function instructions are stored in the program executable(and its dynamic or static libraries) but if this is true what happens when you create a function pointer? AFAIK function pointers point to locations in RAM memory, can they point to locations in program binaries? If yes, how does this work?
Can anyone explain to me how this works and point out if what I know is right or wrong?
First, you need to understand the role of the linker and what are executables (usually executed in virtual memory) and address spaces & processes. On Linux, read about ELF and the execve(2) syscall. Read also Levine's Linkers & Loaders book and Operating Systems: Three Easy Pieces, and the C++11 standard n3337, and this draft report and a good C++ programming book, with this reference website.
Member functions can be virtual or plain functions.
A plain (non virtual) member function is just like a C function (except that it has this as an implicit, often first, parameter). For example your getA method is implemented like the following C function (outside of the object, e.g. in the code segment of the binary executable) :
int C$getA(A*thisptr) const { return thisptr->m_a; }
then imagine that the compiler is translating p->getA() into C$getA(p)
A virtual member function is generally implemented thru a vtable (virtual method table). An object with some virtual member functions (including destructor) has generally as its first (implicit) member field a pointer to such a table (generated elsewhere by the compiler). Your class A don't have any virtual method, but imagine if it had an additional virtual void print(std::ostream&); method, then your class A would have the same layout as
struct A$ {
struct A$virtualmethodtable* _vptr;
int m_a;
};
and the virtual table might be
struct A$virtualmethodtable {
void (*print$fun) (struct A$*, std::ostream*);
};
(so adding other virtual functions means simply adding slot inside that vtable);
and then a call like p->print(std::cout); would be translated almost like
p->_vptr.print$fun(p,&std::cout); ... In addition, the compiler would generate as constant tables various virtual method tables (one per class).
NB: things are more complex with multiple or virtual inheritance.
In both cases, member functions don't eat any additional space in the object. If it is non-virtual, it is just a plain function (in the code segment). If it is virtual, it shares a slot in the virtual method table.
NB. If you compile with a recent GCC (i.e. with g++) or with a Clang (so clang++) you could pass it e.g. the -fdump-tree-all flag: it will produce hundreds of dump files showing partly -in a dumped textual form- some internal representations of the compiler, which you could inspect with a pager (e.g. less) or a textual editor. You could also use MELT or look at the assembly code produced with g++ -S -fverbose-asm -O1 ....
All local non static variables and Non virtual functions are saved in code/text segment.
All static and global variables are saved in static data segment.
Class with virtual functions or inherited from a class with virtual functions will inserted a vptr pointer by compiler. Vptr points to a virtual function table which has number of functions slots. Each slot contains the function address which is stored in the code segment.
To understand this you need to learn about memory layout of a program. the code will be shared by the objects. and all objects will have their own copy of data.
Here is a simple C++ class, named A:
class A
{
public:
explicit A() : m_a(0) { }
explicit A(int a) m_a(a) { }
int getA() const { return m_a; }
void setA(int a) { m_a = a; }
private:
int m_a;
}
This is what I know so far:
When you declare an object of a class instance, memory gets allocated for that object. The allocated memory is equivalent to the memory of its members summed up. So in my case, it is:sizeof(A) = sizeof(int) = sizeof(m_a)
All member functions of class A are stored somewhere in memory and all instances of class A use the same member functions.
This is what I don't know:
Where are member functions stored and how are they actually stored? Let's say that an int for example is stored on 4 bytes; I can imagine the RAM memory layout with 4 contiguous cells each storing a part of that int. How can I imagine this layout for a function?(this could sound silly, but I imagine functions must have a place in memory because you can have a pointer point to them). Also how and where are function instructions stored? My first perception was that functions and function instructions are stored in the program executable(and its dynamic or static libraries) but if this is true what happens when you create a function pointer? AFAIK function pointers point to locations in RAM memory, can they point to locations in program binaries? If yes, how does this work?
Can anyone explain to me how this works and point out if what I know is right or wrong?
First, you need to understand the role of the linker and what are executables (usually executed in virtual memory) and address spaces & processes. On Linux, read about ELF and the execve(2) syscall. Read also Levine's Linkers & Loaders book and Operating Systems: Three Easy Pieces, and the C++11 standard n3337, and this draft report and a good C++ programming book, with this reference website.
Member functions can be virtual or plain functions.
A plain (non virtual) member function is just like a C function (except that it has this as an implicit, often first, parameter). For example your getA method is implemented like the following C function (outside of the object, e.g. in the code segment of the binary executable) :
int C$getA(A*thisptr) const { return thisptr->m_a; }
then imagine that the compiler is translating p->getA() into C$getA(p)
A virtual member function is generally implemented thru a vtable (virtual method table). An object with some virtual member functions (including destructor) has generally as its first (implicit) member field a pointer to such a table (generated elsewhere by the compiler). Your class A don't have any virtual method, but imagine if it had an additional virtual void print(std::ostream&); method, then your class A would have the same layout as
struct A$ {
struct A$virtualmethodtable* _vptr;
int m_a;
};
and the virtual table might be
struct A$virtualmethodtable {
void (*print$fun) (struct A$*, std::ostream*);
};
(so adding other virtual functions means simply adding slot inside that vtable);
and then a call like p->print(std::cout); would be translated almost like
p->_vptr.print$fun(p,&std::cout); ... In addition, the compiler would generate as constant tables various virtual method tables (one per class).
NB: things are more complex with multiple or virtual inheritance.
In both cases, member functions don't eat any additional space in the object. If it is non-virtual, it is just a plain function (in the code segment). If it is virtual, it shares a slot in the virtual method table.
NB. If you compile with a recent GCC (i.e. with g++) or with a Clang (so clang++) you could pass it e.g. the -fdump-tree-all flag: it will produce hundreds of dump files showing partly -in a dumped textual form- some internal representations of the compiler, which you could inspect with a pager (e.g. less) or a textual editor. You could also use MELT or look at the assembly code produced with g++ -S -fverbose-asm -O1 ....
All local non static variables and Non virtual functions are saved in code/text segment.
All static and global variables are saved in static data segment.
Class with virtual functions or inherited from a class with virtual functions will inserted a vptr pointer by compiler. Vptr points to a virtual function table which has number of functions slots. Each slot contains the function address which is stored in the code segment.
To understand this you need to learn about memory layout of a program. the code will be shared by the objects. and all objects will have their own copy of data.
Suppose I have some simple classes/structs without anything but data and a select few operators. If I understand, a basic struct with only data in C++, just like C, occupies as much memory as the members. For example,
struct SomeStruct { float data; }
sizeof(SomeStruct) == sizeof(float); // this should evaluate to true
What I'm wondering is if adding operators to the class will make the object larger in memory. For example
struct SomeStruct
{
public:
SomeStruct & operator=(const float f) { data = f; return this; }
private:
float data;
}
will it still be true that sizeof(SomeStruct) == sizeof(float) evaluates to true? Are there any operators/methods which will not increase the size of the objects in memory?
The structure may not necessarily be only as large as its members (consider padding and alignment), but you are basically correct, in that:
Functions are not data, and are not "stored" inside the object type.
That said, watch out for the addition of virtual table pointers in the case where you add a virtual function to your type. This is a one-time size increase for the type, and does not re-apply when you add more virtual functions.
What I'm wondering is if adding operators to the class will make the object larger in memory.
The answer is "it depends".
If the class wasn't polymorphic prior to adding the function and this new function keeps the class non-polymorphic, then adding this non-polymorphic function does nothing to the size of your class instances.
On the other hand, if adding this new function does make your class polymorphic, this addition will make instances of your class bigger. Most C++ implementations use a virtual table, or vtable for short. Each instance of a polymorphic class contains a pointer to the vtable for that class. Instances of non-polymorphic classes don't need and thus don't contain a vtable pointer.
Finally, adding yet another virtual function to a class that is already polymorphic does not make the class instances bigger. This addition does makes the vtable for that class bigger, but the vtable itself isn't a part of the instance. A vtable pointer is a part of the instance, and that pointer is already a part of the class layout because the class is already polymorphic.
When I was learning about C++ and OOP, I read somewhere (some bad source) that objects in C++ are essentially the same thing as C structs with function pointers inside of them.
They may be like that functionally, but if they were really implemented like that, it would have been a huge waste of space since all object instances would have to store the same pointers.
Method code is stored in one central location and C++ just makes it conveniently look like as if each instance had its methods inside of it.
(Operators are essentially functions with different syntax).
Methods and operators defined inside classes do not increase the size of instantiated objects. You can test it out for yourself:
#include <iostream>
using namespace std;
struct A {
int a;
};
struct B {
int a;
//SOME RANDOM METHODS AND OPERATORS
B() : a(1) {cout<<"I'm the constructor and I set 'a' to 1"<<endl;}
void some_method() const { for(int i=0;i<40;i++) cout<<"loop";}
B operator+=(const B& b){
a+=b.a;
return *this;
}
size_t my_size() const { return sizeof(*this);}
};
int main(){
cout<<sizeof(A)<<endl;
cout<<B().my_size()<<endl;
}
Output on a 64 bit system:
4
I'm the constructor and I set 'a' to 1
4
==> No change in size.
C++ supports inheritance.
But how is it implemented in the compiler?
Does the compiler copy and paste all the implementation from parent to child?
EXTREMELY simplified, if we are talking about something like this:
class A
{
public:
int func1() { do something; }
int func2() { do something; }
};
class B : public A
{
public:
int func2() { do somethign else; }
};
B b;
b.func1();
then what happens inside the compiler will be this (remember, this is VERY simplified, and the real compiler code will be a lot more complex, I'm sure):
... fname = "func1" from the source code ...
... object = "b";
function fn;
while (!(fn = find_func(object, fname)))
object = parent_object(object);
if (fn)
produce_call(fn);
else
print_error_not_found(fname);
If we are talking about virtual functions, then the compiler will produce a table which holds the address of the respective virtual function, and the table is generated for each class, based on a similar principle of "find the function that exists in a this class or one of its parents).
[In the above, I've ignored the fact that one class can have more than one "parent" class - it doesn't change how things works, just that the code has to maintain a list or array of "more classes at the same level"]
Just like member variables, base classes cause a subobject to be embedded inside all instances of the derived class. Member functions of the base class are not duplicated for the derived class, instead they are called on this subobject corresponding to the base class.
The compiler knows where this subobject is located relative to the full object, and will insert pointer arithmetic everywhere there is a cast (possibly implicit) between pointer (or reference) to derived and to base. This includes the hidden this-pointer arguments passed to member functions of the base type.
Virtual inheritance is a little bit tricky, because the offset can be different depending on the most-derived type. In that case, the compiler needs to store the offset as a variable inside the class instances so it can be looked up at runtime (just like pointers to virtual member functions, there might be another layer of indirection involved to save space).
class A (say), having all static member functions only
class B(say) having only member functions
If i create 1000 instances of class A. As the class contains only static member functions, the memory do not increase even if there are 1 instance or 1000 instances.
However, for class B. If i create 1000 instances, will there be an increase of memory (even the slightest, may be a pointer for each object pointing to set of member functions) ?
If no, then how does the compiler keep tracks of member function information for a particular object ?
Will there be an increase of memory (even the slightest, may be a pointer for each object pointing to set of member functions)?
NO.
Non virtual Member functions do not contribute towards size of objects of a class.
However, presence of a virtual member function will typically increase the size of an class object.
Note that the latter is purely implementation specific detail but Since all known compilers implement the virtual mechanism using v-table and v-ptr, it is reasonable to assume that almost all compilers will show the same behavior of adding a v-ptr to every object of that polymorphic class thus increasing size of the class object by size equivalent to that of v-ptr.
For starters, you might try outputting sizeof(A) and sizeof(B). But
several things to keep in mind:
Regardless of the number or types of members, C++ forbids a class to
have a size of 0, so static members or not, each instance of A will
take some memory; and
The resolution of non-virtual functions is done entirely at compile
time, so there is no need for the compiler to add anything to the
class for it. (Virtual functions will typically add the size of one
pointer to the class, regardless of how many virtual functions your
class has.)
If we're just talking about member functions, the imprint will be the same. A member function does not take up more memory the more times the class it is contained within is instantiated (as the this pointer is passed to it). Only the data members of the class are going to take up more memory with each class instantiation as they are unique to each instance of the class.
So to answer your second question, it keeps "track" by the user of the this pointer which is passed when calling a non-static member function of a class.
Things get a bit more complicated with virtual methods, but your question has not covered that particular idiom.
You can use sizeof function to test does function occupy class object's memory.
class A{};
class B{
void foo(){};
};
class C{
static void foo();
};
class D{
virtual void foo();
};
class E{
virtual void foo1();
virtual void foo2();
}
sizeof(A)=1
sizeof(B)=1
sizeof(C)=1
sizeof(D)=4
sizeof(E)=4
First class A B C object's memory is zero. But if they memory is zero ,compile will cann't distinguish those class. So compile add char to distinguish those class. So :
sizeof(A)=1
sizeof(B)=1
sizeof(C)=1
So you can find that member functions and static member functions don't occupy memory.So they will not increasing memory.
But if class has virtual function, it will add 4 byte.And it only add 4 byte whether is have how many virtual functions.Because it only add a vptr point to virtual table, which hold virtual function's point.
At a lower level, there are no objects, just function calls. An implicit this parameter is passed to member functions. When we call void B::f(){ mem1(); }, compiler sees it as B::mem1(this). So even if you have millions of objects of class B, there will be a single function mem1 expecting an object of type class B.
Virtual functions are different. They are looked up from a table, however, lookup result depends on [actual] type of this (in mem1(this)) and not the object pointed by this.
The difference between a static member function and a normal member function is simple. When you call a normal member function the ecx register is set to the address of class instance
you can see an additional
lea ecx, instance_name[ebp]
if you deassemble
the member function uses this register for accessing the class
so the memory usage will not increase but the computational time will increase