«Небезопасная» вещь в том, что перед тем, как назначить ptr новый объект, вам следует задуматься о судьбе того, на что в действительности указывает ptr.
foo.bar(three());
небезопасно в том смысле, что вы должны допустить, прежде чем называть это, что ptr фактически указывает на что-то. В вашем случае это указывает на то, что было создано foo.bar(b);
Но foobar(b)
заставляет ptr
указывать на новый объект, забывая тот, который создан foobar(a)
Более правильный код может быть
template<class T>
class Foo
{
T* p;
public:
Foo() :p() {}
~Foo() { delete p; }
void bar(T& t) { delete p; ptr = new T(t); }
void bar(const T& t) { delete p; ptr = new T(t); }
void bar(T&& t)
{
if(!ptr) ptr = new T(std::move(t));
else (*ptr) = std::move(t);
}
}
;