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
Related
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.
I have a confusion regarding vtable after reading more about name mangling.
for ex:
class Base
{
public:
virtual void print()
{
}
};
class A : public Base
{
public:
void hello()
{
....
}
void print()
{
}
};
A obj;
obj.hello();
Base* test = new A();
test->print();
As per my understanding after the name manging obj.hello() call will be converted to something like _ZASDhellov(&obj) now
how this virtual functions will be invoked from vtable?
my wild guess test->__vtable[_ZASDprintv](&test(dynamic cast to derived???)) is correct?
How the function names are resolved from vtable?
Firstly, vtables are not in any way part of the C++ language, but rather an implementation detail used by particular compilers. Below I describe one way it is commonly used as such.
Second, your function hello is not virtual. To make it virtual, you would simply pre-pend virtual to the declaration.
Assuming it is now virtual: Your guess is quite close. In fact, the vtable (to which a pointer is stored with every instance of a virtual class) is an array of function pointers. The way that a particular function is looked up in it is by its ordinal. The first declared virtual function in A is the first entry in its vtable, the second one is the second entry and so on. If A had a base class, the index of A's first (non-override) virtual function in the table would be n+1, where n is the index of the last virtual function of its base class. If A has more than one base class, their entries precede A's entries in order of their declaration as base classes of A.
If A uses virtual inheritance, the picture is a bit more complicated than that, I won't elaborate unless you're specifically interested.
UPDATE: I'll add a very brief description for the virtual inheritance case as requested. If A had Base as a virtual base class, A's vtable would store at the very beginning (before the function addresses) the byte offset of where Base's data starts within the A object. This is necessary because, unlike in normal inheritance, a base class does not have its data precede the derived class's data - instead it follows it. So in effect, any function call to a virtual function defined in Base has to have its this pointer offset by that amount. Additionally, Base would have to have its own vtable pointer, right at the beginning of its data where it expects to find it. Thus the full A object would contain two vtable pointers instead of one. The actual vtable pointed to by this second pointer would be the same one as the first vtable pointer, except advanced to skip the offset entry described above (so that any Base code using the vtable would find the first virtual function at the beginning where it is expected). Apart from these differences, the vtable itself is the same as before.
Is it "safe" (and/or portable) to call a member function (pointer) on the pointer of a base class, but the object pointed to is an instance different derived class. The member function does not access any member variables or functions of the derived class.
/* Shortened example of what happens in the client code and library */
class Base { /* ... */ }
class DerivedA : public Base {
/* ... */
public: void doSomethingA(float dt);
}
void DerivedA::doSomethingA(float dt) {
/* Does not access members. Conventionally calls/accesses statics */
cout << "dt(" << dt << ")";
}
class DerivedB : public Base { /* ... */ }
typedef void (Base::*SEL_SCHEDULE)(float);
SEL_SCHEDULE pCallback = (SEL_SCHEDULE)(&DerivedA::doSomethingA);
DerivedB db = new DerivedB();
Base *b = &db;
/* pCallback and b are saved in a list elsewhere (a scheduler) which calls */
(b->*pCallback)(0.f);
This seems to work (in MSVC/Debug mode) okay at runtime, but I'm wondering whether this is Bad (TM) - and why? (I'm yet to test this code with the compilers for Android and iOS).
Some more specifics if required: I'm building a cocos2d-x based project. Base is CCObject, DerivedA and DerivedB are subclasses of CCLayer.
The hierarchy is DerivedA and DerivedB < CCLayer < CCNode < CCObject. They're game scenes which are visible/alive at mutually exclusive times.
DerivedA has a different static function to set up playback of music which receives a CCNode caller object as a parameter and schedules another selector (doSomethingA) to begin playback and slowly fade it in using something like:
callerNode->schedule(schedule_selector(DerivedA::doSomethingA), 0.05f);
schedule_selector is what does the C-style cast. doSomethingA does not access any of its member variables or call member functions. It accesses static members and calls other static functions such as such as
CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(sFadeMusicVolume);
The call to doSomethingA at runtime happens in CCTimer::update.
The hack is primarily to avoid duplicating code and conform to the library's callback signature (timer/scheduler system).
It's UB.
You can even use static_cast instead of the odious C-style cast, and the cast itself is quite legal. But
[Note: although class B need not contain the original member, the
dynamic type of the object on which the pointer to member is
dereferenced must contain the original member; see 5.5. —end note ] (5.2.9 12)
"The first operand is called the object expression. If the dynamic
type of the object expression does not contain the member to which the
pointer refers, the behavior is undefined" (5.5 4)
I.e., you go undefined when you call it from an object of dynamic type DerivedB.
Now, as a dirty hacks goes, it's probably not the worst (better than the manual traversing of vtables), but is it really needed? If you don't need any dynamic data, why call it on DerivedB? Base is in the library, you cannot redefine it. Callback is librarian, too, so you have to have this typedef void (Base::*SEL_SCHEDULE)(float);, OK. But why can't you define doSomething for B and make pointer to it to couple with an instance of DerivedB? You say
doSomethingA does not access any of its member variables or call
member functions. It accesses static members and calls other static
functions
But you can do it in doSomethingB as well. Or, if your callbacks are completely uncoupled from object types, and the only reason you need a member function pointer is the conformance to the library callback signature, you can make your actual callbacks non-member plain old functions, and call them from one-line members-callback conformers like DoSomething(float dt) {ReallyDoSomething(dt);}.
I'm wondering whether this is Bad (TM)
It certainly is, unless it's an override of a virtual function declared in a common base class.
If it is, then you don't need the dodgy cast; just initialise directly from &Base::DoSomethingA.
If it isn't, then the evil C cast (which here is a reinterpret_cast in disguise) allows you to apply the pointer to a type that doesn't have that member function; calling that Frankensteinian abomination could do absolutely anything. If the function doesn't actually touch the object, then there's a good chance that you won't see any ill effects; but you're still firmly in undefined behaviour.
It is not safe in general.
You have broken the type-safety system with a C-style cast of your callback in this line:
SEL_SCHEDULE pCallback = (SEL_SCHEDULE)(&DerivedA::doSomethingA);
A member function of DerivedA should operate on an instance of a DerivedA only (or something that further derives from it). You don't have one, you have a DerivedB, but because of your C-cast, your code compiled.
If your callback function had actually tried to access a member of a DerivedA you would potentially have had serious issues (undefined behaviour).
As it is the function only prints so in this case is probably not undefined, but that doesn't mean you should do it.
One typesafe way is to use a callback that takes a Base (reference) and a float and use boost::bind or std::bind to create it.
The other simple way which will probably be your answer most of the time is to just call a virtual method of Base that takes a float.
It is usually allowed to do something like that (no comments on the code please :-))
class SimpleClass {
int member;
};
SimpleClass instance;
int* pointer = (int*) &instance;
However, if I define my class as:
class SimpleClass {
virtual void foo();
int member;
};
I can't do that anymore. Well, I guess I can, of course; it's just more complex.
So I was wondering: is it somewhere specified, or the only way to know when I can do that is just to use some common sense? Not counting alignment issues, which can usually be solved
Generally you want to keep the innards of a class of closed off from the outside world as you can, but if you do need to access a member directly simply specify it as public and take a pointer directly to it.
class SimpleClass {
public:
int member;
};
SimpleClass instance;
int* pointer = &instance.member;
I would avoid accessing the members in the way you describe because as you noted small changes in the class can mess it up, which may be fine whilst you are writing the code but when you come back to it much later you will probably overlook such subtleties. Also unless the class is constructed entirely of native data types, I believe the compiler's implementation will affect the required offset as well.
You can only do this safely if your class is plain old data (POD).
From Wikipedia:
A POD type in C++ is defined as either a scalar type or a POD class. A POD class has no user-defined copy assignment operator, no user-defined destructor, and no non-static data members that are not themselves PODs. Moreover, a POD class must be an aggregate, meaning it has no user-declared constructors, no private nor protected non-static data, no base classes and no virtual functions. The standard includes statements about how PODs must behave in C++.
See this page for many details on POD types. In particular,
"A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member ... and vice versa" [§9.2, ¶17].
class SimpleClass {
int member;
};
SimpleClass instance;
int* pointer = (int*) &SimpleClass;
In the above code pointer points to SimpleClass::member and hence you can access SimpleClass::member in this way.
Once you add an virtual method to the class SimpleClass, the memory map of the object changes.
class SimpleClass {
virtual void foo();
int member;
};
Every object of SimpleClass now contains a special pointer called as vptr which points to a vtable which is a table of addresses of all virtual functions in SimpleClass. The first 4 bytes of every object of SimpleClass now point to the vptr and not SimpleClass::member and that is the reason you cannot access member in the same way as first case.
Ofcourse, virtual behavior is implementation detail of compilers and vptr nor vtable are specified in the standard but the way i mentioned is how most compilers would implement it.
Since the implementation detail might be different for each compiler you should rely on accessing class members through pointers to class(especially polymorphic classes). Also, doing so defeats the entire purpose of Abstraction through Access Specifiers.
All right, several things.
Your first code example won't compile because you can't have a pointer to a class. I think you meant this:
SimpleClass instance;
int* pointer = (int*) &instance;
(Please don't code you haven't tried compiling.)
This kind of casting is powerful and dangerous. You could just as well cast to a pointer to some type (say, char*) and as long as it was a type no larger than int, the code would compile and run. This kind of reinterpretation is like a fire axe, to be used only when you have no better choice.
As it is, pointer points to the beginning of 'instance', and instance begins with instance.member (like every instance of SimpleClass), so you really can manipulate that member with it. As soon as you add another field to SimpleClass before member, you mess up this scheme.
In your second code example, you can still use pointer to store and retrieve an int, but you're doing so across boundaries within the memory structure of instance, which will damage instance beyond repair. I can't think of a good metaphor for how bad this is.
In answer to your questions: yes, this is specified somewhere, and no, common sense isn't good enough, you'll need insight into how the language works (which comes from playing around with questions like this).
My question is not about calling a virtual member function from a base class constructor, but whether the pointer to a virtual member function is valid in the base class constructor.
Given the following
class A
{
void (A::*m_pMember)();
public:
A() :
m_pMember(&A::vmember)
{
}
virtual void vmember()
{
printf("In A::vmember()\n");
}
void test()
{
(this->*m_pMember)();
}
};
class B : public A
{
public:
virtual void vmember()
{
printf("In B::vmember()\n");
}
};
int main()
{
B b;
b.test();
return 0;
}
Will this produce "In B::vmember()" for all compliant c++ compilers?
The pointer is valid, however you have to keep in mind that when a virtual function is invoked through a pointer it is always resolved in accordance with the dynamic type of the object used on the left-hand side. This means that when you invoke a virtual function from the constructor, it doesn't matter whether you invoke it directly or whether you invoke it through a pointer. In both cases the call will resolve to the type whose constructor is currently working. That's how virtual functions work, when you invoke them during object construction (or destruction).
Note also that pointers to member functions are generally not attached to specific functions at the point of initalization. If the target function is non-virtual, they one can say that the pointer points to a specific function. However, if the target function is virtual, there's no way to say where the pointer is pointing to. For example, the language specification explicitly states that when you compare (for equality) two pointers that happen to point to virtual functions, the result is unspecified.
"Valid" is a specific term when applied to pointers. Data pointers are valid when they point to an object or NULL; function pointers are valid when they point to a function or NULL, and pointers to members are valid when the point to a member or NULL.
However, from your question about actual output, I can infer that you wanted to ask something else. Let's look at your vmember function - or should I say functions? Obviously there are two function bodies. You could have made only the derived one virtual, so that too confirms that there are really two vmember functions, who both happen to be virtual.
Now, the question becomes whether when taking the address of a member function already chooses the actual function. Your implementations show that they don't, and that this only happens when the pointer is actually dereferenced.
The reason it must work this way is trivial. Taking the address of a member function does not involve an actual object, something that would be needed to resolve the virtual call. Let me show you:
namespace {
void (A::*test)() = &A::vmember;
A a;
B b;
(a.*test)();
(b.*test)();
}
When we initialize test, there is no object of type A or B at all, yet is it possible to take the address of &A::vmember. That same member pointer can then be used with two different objects. What could this produce but "In A::vmember()\n" and "In B::vmember()\n" ?
Read this article for an in-depth discussion of member function pointers and how to use them. This should answer all your questions.
I have found a little explanation on the Old New Thing (a blog by Raymond Chen, sometimes referred to as Microsoft's Chuck Norris).
Of course it says nothing about the compliance, but it explains why:
B b;
b.A::vmember(); // [1]
(b.*&A::vmember)(); // [2]
1 and 2 actually invoke a different function... which is quite surprising, really. It also means that you can't actually prevent the runtime dispatch using a pointer to member function :/
I think no. Pointer to virtual member function is resolved via VMT, so the same way as call to this function would happen. It means that it is not valid, since VMT is populated after constructor finished.
IMO it is implementation defined to take address of a virtual function. This is because virtual functions are implemented using vtables which are compiler implementation specific. Since the vtable is not guaranteed to be complete until the execution of the class ctor is done, a pointer to an entry in such a table (virtual function) may be implementation defined behavior.
There is a somewhat related question that I asked on SO here few months back; which basically says taking address of the virtual function is not specified in the C++ standard.
So, in any case even if it works for you, the solution will not be portable.