Если нет других соображений, предпочтителен метод 2.
Векторы (и другие контейнеры STL) хранят копии аргумента для push_back ().
Это означает, что для метода 1 вы выделяете Foo в куче, а затем сохраняете указатель на него в векторе. Если объект User уничтожен, объекты Foo будут вытекать, если вы не предпримете шаги для их удаления (например, удалите их в деструкторе User).
Для метода 2 вы разместили Foo в стеке. Этот объект затем копируется в вектор. При выходе из start () исходный Foo уничтожается, но копия сохраняется в векторе. Если объект User уничтожен, то и вектор, и, следовательно, Foo.
Для метода 3 вы разместили Foo в стеке. Затем вы вызываете GiveMeFoo () для него, который выделяет другой Foo в куче, а затем возвращает указатель на него. Этот указатель затем копируется в вектор. При выходе из start () исходный Foo будет уничтожен, но объект, выделенный в куче, сохранится. Если объект User уничтожен, то и вектор, но выделенная куча Foo, выживает и утекает, если вы не уничтожите его вручную в деструкторе User.
Если вам нужно хранить указатель на объект, а не на копию, лучше использовать std :: tr1 :: shared_ptr (если ваш компилятор поддерживает это) для управления временем жизни объектов Foo.