I was recently told in a code review (by an older and wiser C++ developer) to rewrite a class I'd written turning it into a set of static methods instead. He justified this by saying that although my object did contain a very small amount of internal state, it could be derived at runtime anyway and if I changed to static methods I'd avoid the cost of insantiating objects all over the place.

I have now made this change but it got me to thinking, what is the cost of instantiation in C++? I'm aware that in managed languages, there's all the cost of garbage collecting the object which would be significant. However, my C++ object was simply on the stack, it didn't contain any virtual methods so there would be no runtime function lookup cost. I'd used the new C++11 delete mechanism to delete the default copy/assignment operators so there was no copying involved. It was just a simple object with a constructor that did a small amount of work (required anyway with static methods) and a destructor which did nothing. Can anyway tell me what these instation consts would be? (The reviewer is a bit intimidating and I don't want to look stupid by asking him!) ;-)

You never look stupid for asking questions. If he thinks you are then HE IS STUPID. Asking is how we better ourselfs.
–
IznogoodFeb 28 '12 at 21:39

@spencercw: But why make a function a member function if it can be static? Even from a design perspective that makes no sense.
–
Ed S.Feb 28 '12 at 21:41

@EdS.: Are you asserting that there is no place in the world for static member functions? I'm not necessarily disagreeing, but that's a pretty grandiose claim; I'm not sure that there's anywhere near the sort of consensus on that to decide that the alternative "makes no sense"
–
Lightness Races in OrbitFeb 28 '12 at 21:42

1

@spencercw: I was actually under the impression that these would not be member functions at all, but instead free functions.
–
Ed S.Feb 28 '12 at 21:45

6 Answers
6

If your object-type must invoke a non-trivial constructor and destructor during it's life-time, then the cost is the going to be the minimum cost of creating any C++ object that has a non-trivial constructor and destructor. Making the rest of your methods static will not reduce that cost. The "price" of space will be at least 1 byte since your class is not a base-class of a derived class, and the only cost-savings in the static class method calls will be the omission of the implicit this pointer passed as the hidden first argument of the call, something that would be required for non-static class methods.

If the methods your reviewer is asking you to re-designate as static never touch the non-static data-members of your class-type, then the passing of the implicit this pointer is a wasted resource, and the reviewer has a good point. Otherwise, you would have to add an argument to the static methods that would take the class-type as either a reference or pointer, nullifying the gained performance from the omission of the implicit this pointer.

I think the idea is that the class would become uninstantiable; i.e. he really should be using a namespace instead.
–
Lightness Races in OrbitFeb 28 '12 at 21:40

@LightnessRacesinOrbit: Yeah, if it is only a set of static functions than the class is not needed, but the OP said that the class did in fact maintain "minimal" amounts of state.
–
Ed S.Feb 28 '12 at 21:43

@EdS.: ... and that it was suggested that that state could instead be derived when needed
–
Lightness Races in OrbitFeb 28 '12 at 21:48

The issue though is the OP said that a non-trivial constructor is necessary, therefore there is most likely some type of state variable per-instance, rather than a global state. Otherwise why would a non-trivial constructor be necessary? So if that is the case, then there are two issues ... methods that must access the local state, and methods that don't need to. Those that don't need to can be static, but those that must will either have to pass the instance by reference or pointer, negating the benefit of making them static from a call-efficiency perspective.
–
JasonFeb 28 '12 at 21:53

Short answer - inherently object allocation is cheap but can get expensive in certain cases.

Long Answer

In C++ the cost of instantiating an object is the same as instantiating a struct in C. All an object is, is a block of memory big enough to store the v-table (if it has one) and all the data attributes. Methods consume no further memory after the v-table has been instantiated.

A non-virtual method is a simple function with an implicit this as its first parameter. Calling a virtual function is a bit more complicated since it must to a v-table lookup in order to know which function of which class to call.

This means that instantiating a object on the stack involves a simple decrement of the stack pointer (for a full decending stack).

When an object is instantiated on the heap, the cost can go up substantially. But this is something inherent with any heap related allocation. When allocating memory on the heap, the heap needs to find a free block big enough to hold your object. Finding such a block is a non-constant time operation and can be expensive.

C++ has constructors that may allocated more memory for certain pointer data attributes. These are normally heap allocated. This is further compounded if said data members perform heap allocations themselves. This can lead to something involving a substantial number of instructions.

So bottom line is that it depends on how and what the object is that you are instatiating.

This is more or less what I understood to be the case. In my case, as I said in my question, there are no vtables to deal with and no dynamic memory allocation. So really, the only extra cost is the implicit this pointer passing. Which given that the code isn't performance critical probably means that the change wouldn't even be measurable in performance terms. However, probably the right thing to do from a style/design point of view.
–
BenjFeb 29 '12 at 9:31

Probably not a lot, and I'd be amazed if it were any sort of bottleneck. But there's the principle of the thing if nothing else.

However, you should ask the guy; never be afraid to do that, and it's not entirely clear here that losing the stored state and instead deriving it each time (if that's what you're doing instead) is not going to make things worse. And, if it's not, you'd think a namespace would be better than static methods.

A testcase/example would make this easier to answer categorically, further than "you should ask him".

As a general rule, if a function can be made static it probably should be. It is cheaper. How much cheaper? That depends on what the object does in its constructor, but the base cost of constructing a C++ object is not that high (dynamic memory allocation of course is more expensive).

The point is not to pay for that which you do not need. If a function can be static, why make it a member function? It makes no sense to be a member function in that case. Will the penalty of creating an object kill the performance of your application? Probably not, but again, why pay for what you don't need?

It depends on what your application does. Is it a real time system on a device with limited memory? If not, most of the time object instantiation won't be an issue, unless you are instantiating millions of these and keeping them around or some weird design like that.
Most systems will have a lot more bottlenecks such as:

user input

network calls

database access

computation intensive algos

thread switching costs

system calls

I think in most cases encapsulation into a class for design trumps small costs of instantiation. Of course there can be those 1% of cases where this doesn't hold but is yours one of those?

As others have suggested talk to your colleague and ask him to explain his reasoning. If practical, you should investigate with a small test program the performance of the two versions. Doing both of these will help you grow as a programmer.

In general I agree with the advice to make a member function static if practical. Not because of performance reasons but because it reduces the amount of context you need to remember to understand the behaviour of the function.

It is worth noting that there is one case where using a member function will result in faster code. That case is when the compiler can perform inlining. This is kind of an advanced topic but it is stuff like that makes it hard to write categorical rules about programming.

On my i7 Linux because g++ can't inline the function int_lt but can inline std::less::operator() the non member function version is about 50% slower.

> g++-4.5 -O2 p3.cc
> ./a.out
3.85
5.88

To understand why such a big difference you need to consider what type the compiler infers for the comparator. In the case int_lt it infers the type bool (*)(int, int) whereas with std::less it infers std::less. With the function pointer the function to be called is only ever known at run time. Which means that it is impossible for the compiler to inline its definition at compile time. In contrast with std::less the compiler has access to the type and its definition at compile time so it can inline std::less::operator(). Which makes a significant difference to performance in this case.

Is this behaviour only related to templates? No, it relates to a loss of abstraction when passing functions as objects. A function pointer does not include as much information as a function object type for the compiler to make use of. Here is a similar example using no templates (well aside from std::vector for convenience).

Hmm, I was aware that inlined comparator functions could dramatically effect performance of sort etc but I was unaware that a functor was any more likely to be inlined than a free function. Can you explain why this is?
–
BenjFeb 29 '12 at 9:25

Benj it is not about templates but about levels of abstraction that the compiler can and can't work with. Please let me know if I can provide any further clarification. Also do watch the talk by Bjarne Stroustrup it is very interesting.
–
Bowie OwensFeb 29 '12 at 23:19