🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

C++ tutorials

Started by
93 comments, last by taby 1 year, 9 months ago

Gnollrunner said:
Ha, ha, yet another C++ war. Just use it however it suits you.

Sadly that's no solution. War always rises from others not using it the way which would suit you. ;D

Advertisement

I don't see any war here. It's important that we be picky about details with C++ - a small detail overlooked can introduce failure modes that aren't a thing with other languages/technologies. And it's important that we ensure we all know about the important details and not get caught up in mental models that don't apply, because someday someone reading this thread may be in a position to work on a C++ codebase and it is in their and their coworkers' interests that they know these things.

I'm too old to get into wars LOL

Oberon_Command said:

I don't see any war here.

I think we should have a war over whether it's a war or not.

Metawar.

Ok, one last newbie question: what benefits are there to using function pointers versus std::function? For instance:

...

void proceed_a(size_t& n)
{
	cout << "proceed_a()" << endl;
}

void proceed_b(size_t& n)
{
	cout << "proceed_b()" << endl;
}

void proceed_c(size_t& n)
{
	cout << "proceed_c()" << endl;
}

void proceed_d(size_t& n)
{
	cout << "proceed_d()" << endl;
}

// Function pointer typedef
typedef void (*proceed_func_pointer)(size_t&);

...

size_t param = 1234;

// Pointer to function example
proceed_func_pointer p = &proceed_a;
(*p)(param); // Call function

// Try using std::function instead of a pointer to function
function<void(size_t&)> proceed = proceed_a;
proceed(param);

taby said:
Ok, one last newbie question: what benefits are there to using function pointers versus std::function?

If you're on a small codebase or performance isn't important, not much.

std::function can heap allocate if you give it a capturing lambda with a large enough capture, because it's meant to hold any closure; function pointers don't run into this because they can't store any kind of closure, because they point to the function itself not a type-erased closure. As a template it will also slow your compiles down in a small way (that may add up over time, but it isn't nearly as bad as other standard library types reportedly are) and because C++ does not have a standard ABI, it would be an obstacle for linking code from different compilers together.

Oberon_Command said:
If you're on a small codebase or performance isn't important, not much. std::function can heap allocate if you give it a capturing lambda with a large enough capture, because it's meant to hold any closure; function pointers don't run into this because they can't store any kind of closure, because they point to the function itself not a type-erased closure. As a template it will also slow your compiles down in a small way (that may add up over time, but it isn't nearly as bad as other standard library types reportedly are) and because C++ does not have a standard ABI, it would be an obstacle for linking code from different compilers together.

Agreed, but just want to point out two important (practical) properties of std::function:

  1. Calling the std::function doesn't have any significant overhead over a (member-to) function pointer. I've made several tests a few years back with MSVC, and this came to my suprise. Even when the compiler wasn't able to fully eliminate the std::function, it was not in any way slower than the raw-function pointer on invokation.
  2. The main performance overhead that I experienced came actually from destruction of the object. Even if no capture was given, destructing the std::function objects added a significant overhead (about 10x in my sample) to the entire code. I'm not 100% sure on the details of how this came to be, obviously the type-erasure has to execute some form of destructor but I wouldn't have expected it to be that bad.

I don't have my test-case lying around anymore, so milage may vary on different/more up-to-date compilers, but thats what I've found out. So my conclusion was, that if I want to hold on to function-objects for a very long time, std::function is fine, but if I have to create and destroy them frequently, they are significantly slower.

Juliean said:
Calling the std::function doesn't have any significant overhead over a (member-to) function pointer. I've made several tests a few years back with MSVC, and this came to my suprise. Even when the compiler wasn't able to fully eliminate the std::function, it was not in any way slower than the raw-function pointer on invokation.

That matches my expectations as well - I expect most of the perf loss to be related to the allocations.

Using the Release build, the numbers are close, but not quite the same:

Function pointer method took 1.42315 seconds
Function<> method took 1.97452 seconds

Thanks again for all of your help!

This topic is closed to new replies.

Advertisement