开发者

Can GCC compile classes to work as structs?

Is there any way to force a compiler (well GCC specifically) to make a class compile to object oriented C? Specifically what I want to achieve is to write this:

class Foo {
public:
  float x, y, z;
  float bar();
  int other();
  ...etc
};

Foo f;
float result = f.bar()
int obSize = sizeof(Foo);

Yet compile to exactly the same as:

Struct Foo { float x, y, z; };
float Foo_bar(Foo *this);

Foo f;
float result = Foo_bar(&f);
int obSize = sizeof(Foo);

My motivation is to increase readability, yet not suffer a memory pen开发者_开发知识库alty for each object of Foo. I'd imagine the class implementation normally obSize would be

obSize = sizeof(float)*3 + sizeof(void*)*number_of_class_methods

Mostly to use c++ classes in memory constrained microcontrollers. However I'd imagine if I got it to work I'd use it for network serialization as well (on same endian machines of course).


Your compiler actually does exactly that for you. It might even be able to optimize optimistically by putting the this pointer in a register instead of pushing it onto the stack (this is at least what MSVC does on Windows), which you wouldn't be able to do with standard C calling convention.

As for:

obSize = sizeof(float)*3 + sizeof(void*)*number_of_class_methods
  1. It is plain false. Did you even try it ?
  2. Even if you had virtual functions, only one pointer to a table of functions would be added to each object (one table per class). With no virtual functions, nothing is added to an object beyond its members (and no function table is generated).
  3. void* represents a pointer to data, not a pointer to code (they need not have the same size)
  4. There is no guarantee that the size of the equivalent C struct is 3 * sizeof(float).


C++ already does what you're talking about for non-polymorphic classes (classes without a virtual method).

Generally speaking, a C++ class will have the same size as a C struct, unless the class contains one or more virtual methods, in which case the overhead will be a single pointer (often called the vptr) for each class instance.

There will also be a single instance of a 'vtbl' that has a set of pointers for each virtual function - but that vtbl will be shared among all objects of that class type (ie., there's a single vtbl per-class type, and the various vptrs for objects of that class will point to the same vtbl instance).

In summary, if your class has no virtual methods, it will be no larger than the same C struct. This fits with the C++ philosophy of not paying for what you don't use.

However, note that non-static member functions in a C++ class do take an extra parameter (the this pointer) that isn't explicitly mentioned in the parameter list - that is essentially what you discuss in your question.


footnote: in C++ classes and structs are the same except for the minor difference of default member accessibility. In the above answer, when I use the term 'class', the behavior applies just as well to structs in C++. When I use the term 'struct' I'm talking about C structs.

Also note that if your classes use inheritance, the 'overhead' of that inheritance depends on the exact variety of inheritance. But as in the difference between polymorphic and non-polymorphic classes, whatever that cost might be, it's only brought in if you use it.


No, your imagination is wrong. Class methods take up no space at all in an object. Why not write a class, and take the sizeof. Then add a few more methods and print the sizeof again. You will see that it hasn't changed. Something like this

First program

class X
{
public:
  int y;
  void method1() {}
};

int main()
{
  cout << sizeof(X) << '\n'; // prints 4
}

Second program

class X
{
public:
  int y;
  void method1() {}
  void method2() {}
  void method3() {}
  void method4() {}
  void method5() {}
  void method6() {}
};

int main()
{
  cout << sizeof(X) << '\n'; // also prints 4
}


Actually, I believe there is no specific memory penalty with using classes since member functions are stored once for every instance of the class. So your memory footprint would be more like 1*sizeof(void*)*number_of_class_methods + N*sizeof(float)*3 where you have N instances of Foo.

The only time you get an additional penalty is when using virtual functions in which case each object carries around a pointer to a vtable with it.


You need to test, but as far as i know a class instance does only store pointers to its methods if said methods are virtual; otherwise, a struct and a class will take roughly the same amount of memory (bar different alignment done by different compilers etc).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜