• 13
• 15
• 27
• 9
• 9

# call to new SomeClass() in func parameter

This topic is 757 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi Guys,

A quick question. Say we have a class such as the following...

class MyClass{

std::vector<Entity*> ents;

ents.push_back(ent);

}
~MyClass(){
for(auto it=ents.begin();it!=ents.end();it++)
delete *it;
}
};


Now, somewhere else in the program, I would like to make the following call.

void init(){

}



When I do the above, everything works just file. However, say I would like a client (someone other than myself) to create an Entity, but with out the call to "new". For example, I would like to init like so.

void init(){
Entity e();

}



Now, this does not work as e() goes out of scope, and the pointer in std::vector<Entity*> is not pointer anywhere valid.

My question is, how does one have a client use a class without calling "new".

Thanks,

Mike

##### Share on other sites

Thanks again for the greatly detailed (and invaluble) response Josh.

I did think of using your method, for example Entity* MyClass::addEnt(), but then I considered the following problem.

class MyClass{
std::vector<Ents*> ents;

~MyClass(){
for(auto it=ents.begin();it!=ents.end();it++)
delete *it;
}

};


This is not my problem, just a hypothetical  one. .

How does one avoid bloating the functions? For example we have 200 different types of entities (just a hypothetical) is there a way to avoid 200 void addSomethings()?

Thanks,

Mike

##### Share on other sites

Assuming all those types are Entity subclasses, one option is:

template<typename ClassType, typename... ArgumentTypes>
void addEntity(ArgumentTypes &&... arguments) {
Entity * result = new ClassType(std::forward<ArgumentTypes>(arguments)...);
ents.push_back(result);
return result;
}

Call this as:

MyClass m;
m.addEntity<BarEntity>(parameters, for, bar);

This requires C++11 (at which point you should also move to std::unique_ptr<T>, but I left it out for brevity).

Edited by Josh Petrie

##### Share on other sites

Thanks a bunch Josh. I will try that out.

Mike

##### Share on other sites

One more question that I have been wondering about.

Are there any practical differences between this...

void func(){
ents.push_back(new Ent());
}


and this

void func(){
Ent *ent=new Ent();
ents.push_back(new Ent());

}


if in the destructor we delete all ents?

Thanks,

Mike

##### Share on other sites
In that simple case, they're basically the same, assuming that you typo'd new Ent() in the push_back() call and meant to write push_back(ent) instead.

However, if you use exceptions, the difference becomes more important, especially if you have multiple parameters for a function call. Since parameter evaluation order is implementation-dependent in C++, the following is a problem:

foo.Operate(new Bar(), new Baz());
If the constructor of Bar or Baz throws, you wind up with a potential leak of the other object. This is (one reason) why smart pointers are useful. If you have operations that might throw, the safe thing to do is always store them in intermediate wrappers until needed:

std::unique_ptr<Bar> bar(new Bar());
std::unique_ptr<Baz> baz(new Baz());
foo.Operate(bar, baz);

##### Share on other sites

http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique

It's worth mentioning that you don't need to manually dispose of smart pointers. You may have realized that, but I've seen people do all kinds of strange things with them.

Also, you can now:

for(auto it=ents.begin();it!=ents.end();it++) // not have to deal with this


and

for(auto&& ent : ents) // get to do this instead


Note that 'ent' in this case is not an iterator, but refers directly to the object.