Ask yourself this: what if the underlying OS is not written in C++?
Even if the OS implementation of thread parameters is C++, how could it possibly know what to do with arbitrary things passed around via thread parameters?
Why is the OS relevant? We're in C++ library land, not OS land.
I can write a C++ wrapper around the Windows/Linux OS threading APIs that respects the C++ object model... I would assume the C++ standard library also does so.
std::thread copies/moves all the constructor arguments to temporary storage, then launches the underlying OS thread, then invokes your callback in that thread (passing the args from the temporary storage).
So I'm not sure, but this may be an infinite loop:
1) something has a shared-ptr
2) std::thread's constructor copies it (now two ref's)
3a) DestructionHandler copies it (now three ref's)
4a) something exits and destructs it's shared-tr (now two ref's)
OR
3b) something exits and destructs it's shared-tr (now one ref)
4b) DestructionHandler copies it (now two ref's)
You can pass the arguments by reference instead, and have the main thread block until DestructionHandler runs far enough to make a value-copy from the reference-argument -- that would eliminate any hidden temporaries. That's actually what I do in my own OS-thread wrapper, so that I can pass objects by value without having to keep extra copies around for longer than necessary.