Sign in to follow this  

call to new SomeClass() in func parameter

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi Guys,

 

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

class MyClass{

 std::vector<Entity*> ents;

void addEnt(Entity *ent){

 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(){

 addEnt(new Entity());

}


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();
 addEnt(&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 this post


Link to post
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;
}

void addApple();
void addPear();
void addCucumber();
void add...
void addZuchini();


};

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 this post


Link to post
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<FooEntity>(parameters, for, foo);
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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.

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this