Performance of golang style defer scope guard in C++

800 Views Asked by At

After reading this question on implementing Go's defer in C++:

golang-style "defer" in C++

I had a question on the performance of the go-defer like guard clause in given in one of the answers. It uses a shared_ptr deleter which ignores the passed object address.

If the deleter ignores the address using an unnamed parameter, will it still be passed on the stack.

Will there be any difference in any of the following ways of accomplishing the defer?

#include <memory>
#include <iostream>
#include <functional>

using namespace std;
using defer = shared_ptr<void>;

int main() {
    defer defer0 (nullptr, [](...) { cout << "defer0\n"; }); // this is the version i've seen

    // but will the performance be any different using any of these?
    shared_ptr<int> defer1(nullptr, [](int* dummy) { cout << "defer1\n"; });
    shared_ptr<int> defer2(nullptr, [](int*) { cout << "defer2\n"; });
    shared_ptr<void> defer3(nullptr, [](void*) { cout << "defer3\n"; });

    unique_ptr<int,void(*)(int*)> defer4(nullptr, [](int*) { cout << "defer4\n"; });

    cout << "Hello\n";
}
1

There are 1 best solutions below

0
On

You can check out what is built for each of the implementations here: godbolt.

In short, there's no difference between versions 0-3, the pointer gets passed to the deleter function the same way in each case.

If you're looking for performance though, using a std::shared_ptr for this purpose is not a good idea. Shared pointers need to allocate memory for resource counting, which is totally unnecessary for a finalizer.

The std::unique_ptr case (with a dummy variable so the deleter is actually called) will work with the least overhead. However, a more dedicated class would be more sensible.