The .reset() method of common smart pointers
It seems to me that the reset method in the boost scoped_ptr and shared_ptr lead to incorrect order of construction and destruction:
boost::scoped_ptr<Component> component(GetDefaultComponent());
component.reset(new BetterComponent); // 1. Creation of the new object
// 2. Destruction of the old object
This is the wrong order IMO.
It is possible to first call the reset method without arguments and then set the new pointer. However that seems lik开发者_StackOverflowe a workaround to me. (And it being a "workaround" implies that there is something wrong.)
I am convinced that the boost people are very smart. So there must have been a rationale for the current approach.
Does anyone know more?
It's absolutely the right order. What happens if new BetterComponent
throws? Whoops. This is the same order in which everything happens, it's known as copy-and-swap, and it's the best way to go.
Especially since you didn't actually give any reason that the current order is wrong.
You can always refactor this in a free function (and do beware of the exception-safety consequences):
template<typename T, typename Pointer, typename... U>
void
emplace_reset(Pointer& pointer, U&&... u)
{
pointer.reset();
pointer.reset(new T(std::forward<U>(u)...));
}
// use as: emplace_reset<BetterComponent>(component);
But this is not a workaround because the reset member does just as advertised. What you're asking for is a new functionality.
A possible rationale for not providing the functionality you want (beyond exception-safety/transactional semantics) is that pointers have never, ever created the objects they point to: the constructors assume ownership but that's it. reset
is consistent in that manner.
精彩评论