I thought I'd bring this back up because none of the answers have touched on exactly what your friend has done wrong.
I'm obviously guessing exactly what your instincts picked up on, but I'll give you credit for having excellent instincts and being exactly right (Bravo!).
It is a bit pointless allocating a small class on the heap when all that class does is allocate some memory on the heap, but what's really wrong with it is the code duplication. Your friend's class is responsible for allocating the memory and deleting it. By declaring it with new your friend is taking responsibility for deleting the object, and hence for deallocating the memory so in effect you're coding the memory management twice if the object is using a standard library vector then it doesn't need to do it at all (the std::vector is itself a small class that allocates memory on the heap).
In Java and similar languages any object that isn't a built in type has to be created with the new command. A lot of people take this habit over into c++; but, as you've spotted, it's unnecessary. It's also dangerous.
Using the new command directly should be considered "advanced" c++. Don't do it unless you really need to. Whenever you use a new command you are responsible for making sure there is a matching delete command and that that command is always called exactly once. This is difficult! I'm not saying never do it but you should almost never need to and if you do do it you should be aware that you're doing something advanced and you need to be extra careful. There's probably something in the standard library that does it for you.
There are two ways of dealing with this, you can either say "C++ is scary, I'm going back to Java" or you can just stop using the new command when you don't need to.
You may have heard people say that c++ doesn't have garbage collection. In fact, c++ has a very advanced "garbage collection" mechanism. It's just that it's possible to switch it off.
Here's a short program that simulates an early episode of South Park.
#include<string>
#include<iostream>
using namespace std;
class Character{
string my_name;
public:
Character(string name) : my_name(name){
cout << "Hi I'm " << my_name << " and I've just been born" << endl;
}
~Character(){
cout << "Oh my god, they killed " << my_name << "!" << endl;
}
};
void south_park(){
Character kyle("Kyle");
Character stan("Stan");
Character cartman("Cartman");
cout << "Starting Episode" << endl;
Character ike("Ike");
{
Character kenny("Kenny");
cout << "Some Stuff Happens" << endl;
}
cout << "Some more stuff happens" << endl;
cout << "Kyle learns something today" << endl;
cout << "End of episode" << endl;
}
int main(int, char**){
try{
south_park();
cout << "What a great episode of south park" << endl;
}
catch(...){
cout << "Aww, we didn't finish the episode" << endl;
}
}
When you run the program you'll notice that all the characters are born when the Character class is declared. Kyle, Stan and Cartman are all born before the start of the episode, Ike and Kenny are born after the start of the episode, but Kenny is unfortunate enough to be born within a set of curly brackets.
This means that the variable Kenny is only in scope within the curly brackets. If you try to refer to the variable outside of the curly brackets you get an error. In garbage collected languages the object is simply forgotten about until the memory is needed again, but in c++ the object is destroyed as soon as the object goes out of scope. I don't have to do anything to tell you that the character died, the class takes care of that itself in the destructor. Have a play with the code and see what happens to the characters when you initialise them in different places.
Notice that every character that gets born always dies and that characters always die in the reverse order that they were created. This is automatic! Try putting a return statement or a throw somewhere in the episode. It doesn't matter where you put it, some characters might not get born, but every character that gets born will die before the function returns. This is the key to "garbage collection" (which we call resource management) in c++.
If somewhere in the function I declared
Character* butters = new Character("Butters")
then, unless I explicitly call delete butters, Butters will still be alive at the end of the episode: which in c++ is a bad thing.
In c++ when you use a new command you're effectively saying to the compiler "Please turn garbage collection off because I know what I'm doing" but in a lot of cases you're actually saying "I've just turned garbage collection off because I don't know what I'm doing".
When you allocate memory in c++, or open a file, or do anything that needs to be cleaned up afterwards you should always wrap that in a class which does all the clean-up it needs to do in its destructor and that object should always either be on the stack or a member variable of a class. (member variables are destroyed properly when the class is destroyed)
If some idiot declares your class with new and doesn't delete it that's his problem not yours.
So in my south park program, if one of my characters needs to allocate memory it can do that knowing full well that the destructor will be called exactly once, so it can safely call delete there as long as I make sure that the class keeps track of any resources it has allocated. In fact it's doing that already without you even noticing it.
The string class is 32 bytes (in clang on 64-bit linux) if the string is short enough to fit within the 32 bytes it will store it there. If the string is longer it will allocate the string on the heap, if you change the length of the string it allocates some new memory, copies the string and deletes the old memory. In the destructor it deletes the memory it has allocated. All this is taken care of without you even knowing that it has happened. As long as your string is on the stack that memory will always be deallocated correctly. As soon as you use a new then you're on your own.
That whole principle is called "Resource acquisition is initialisation" or RAII; which everyone agrees is a terrible name which is why I didn't call it that until the end.
There are lots and lots of posts about it on stack overflow plus articles and talks etc if you want to find out more (which you should). Getting this stuff right is the difference between good c++ and bad c++.