I am in the process of making a simulation and it requires the creation of multiple, rather similar models. My idea is to have a class called Model and use static factory methods to construct a model. For example; Model::createTriangle or Model::createFromFile. I took this idea from previous java code and was looking for ways to implement this in C++.
Here is what I came up with so far:
#include <iostream>
class Object {
int id;
public:
void print() { std::cout << id << std::endl; }
static Object &createWithID(int id) {
Object *obj = new Object();
obj->id = id;
return *obj;
}
};
int main() {
Object obj = Object::createWithID(3);
obj.print();
return 0;
}
Some questions about this:
Is this an accepted and clean way of making objects?
Does the returned reference always ensure correct removal of the object?
Is there any way to do this without pointers?
Just for the record, here's how this program might look like in proper C++:
class Object
{
int id;
// private constructor, not for general use
explicit Object(int i) : id(i) { }
public:
static Object createWithID(int id)
{
return Object(id);
}
};
int main()
{
Object obj1 = Object::createWithID(1);
auto obj2 = Object::createWithID(2); // DRY
// return 0 is implied
}
This is probably not what people would generally call a "factory", since factories typically involve some dynamic type selection. The term "named constructor" is sometimes used, though, to refer to the static member function that returns an instance of the class.
Your code currently contains a memory leak: any object created using new, must be cleaned up using delete. The createWithID method should preferably not use new at all and look something like this:
static Object createWithID(int id)
{
Object obj;
obj.id = id;
return obj;
}
This appears to require an additional copy of the object, but in reality return value optimization will typically cause this copy to be optimized away.
Is this an accepted and clean way of making objects?
It is (unfortunately) accepted but it's not clean.
Instead of factory functions just use constructors.
That's what they're for.
Does the returned reference always ensure correct removal of the object?
The reference is irrelevant except to the extent that it misleads users of the function.
In your example the reference has apparently misled yourself into not destroying the dynamically allocated object, but just copying it.
Better return a smart pointer.
But as already mentioned, it's even better to ditch the idea of factory functions.
They're wholly unnecessary here.
Is there any way to do this without pointers?
No, not if "this" refers to the dynamic allocation, but you can and should use constructors instead of factory functions.
Example:
#include <iostream>
namespace better {
using std::ostream;
class Object
{
public:
auto id() const -> int { return id_; }
explicit Object( int const id): id_( id ) {}
private:
int id_;
};
auto operator<<( ostream& stream, Object const& o )
-> ostream&
{ return (stream << o.id()); }
} // namespace better
auto main()
-> int
{
using namespace std;
cout << better::Object( 3 ) << endl;
}
By calling Object *obj = new Object(); you do allocate memory on the heap. In the lines following that statement you do return the reference to that object. So far, so good, but you do never delete the object you created to actually free the memory. By calling the function several times you will run in a memory leak.
There are two possible workarounds:
static Object createWithID(int id); would return a copy of the Object you create, so it would be enough to allocate it on the stack using
Object tmp;
tmp.id = id;
use c++11 smart pointer to let them handle the memory.
#include <memory>
static std::unique_ptr<Object> createWithID(int id)
{
std::unique_ptr<Object> tmp(new Object());
tmp->id = id;
return std::move(tmp);
}
This is an absolutely terrible way to create your objects. Every time that createWithID is called, a new Object is constructed on the free store which is never able to be destroyed.
You should rewrite createWithID to:
static Object createWithID(int id) {
Object obj;
obj.id = id;
return obj;
}
Or better, you could just supply a constructor for your Object objects.
If you want to enable polymorphic objects, you should use something like wheels::value_ptr.
Unless you are using polymorphism there is no reason for your factory functions to return any kind of pointer, they can just return the object by value. Any modern compiler will do return value optimization so there is no copy.
If you are after an "accepted and clean" way then that sounds quite opinion based and dependent on how this class will be used but what I would do is keep the definition of Model as small as possible. Only include what is needed for it to do its job with a minimum number of constructors required for normal usage:
namespace Simulation {
class Model {
private:
int id_;
public:
explicit Model(int id) : id_(id) {}
// minimum required to do the job...
};
}
Then, I would define the functions to create various flavors of Model separately. For example, as non-member, non-friend functions in a namespace:
namespace Simulation {
Model createTriangle(int id) {
Model model(id);
// do whatever you need to do to make it a triangle...
return model;
}
Model createSquare(int id) {
Model model(id);
// do whatever you need to do to make it a square...
return model;
}
}
That way, if you find you need another flavor of Model, you don't need to change the Model class. Your create functions can even be spread across multiple files if needed or become part of a Builder or Factory class. Usage would look like:
int main() {
Simulation::Model m1(0);
Simulation::Model m2 = Simulation::createTriangle(1);
Simulation::Model m3 = Simulation::createSquare(2);
}
Related
To improve performance when creating & destroying object, pooling is a possibility.
In some situation, I don't want to go into low-level techniques like custom allocator or char[].
Another way is to create object pool.
However, this technique doesn't go well with in-class field (inline) initialization.
At first, I didn't think this is a problem at all.
However, the pattern keeps re-appear hundred times, and I think I should have some counter-measure.
Example
Assume that the first version of my program looks like this:-
class Particle{
int lifeTime=100; //<-- inline initialization
//.... some function that modify "lifeTIme"
};
int main(){
auto p1=new Particle();
delete p1;
//... many particle created & deleted randomly ...
};
After the adopt of object pool, my program can be:-
class Particle{
int lifeTime=100; //<---- maintainability issue
void reset(){
lifeTime=100; //<---- maintainability issue
}
};
int main(){
auto* p1=pool.create();
//.... "Particle::reset()" have to be called somewhere.
};
The duplicating code causes some maintainability issue.
Question
How to adopt object-pool to an existing object that has inline-field-initialization without sacrificing code-maintainability and readability?
My current workaround
I usually let the constructor call reset().
class Particle{
int lifeTime;
public: Particle(){
reset(); //<---- call it here, or "pool" call it
}
void reset(){
lifeTime=100;
}
};
Disadvantage: It reduces code-readability comparing to the old inline-initialization:-
int lifeTime=100;
Sorry if it is too beginner question, I am new to C++.
This is a usual usecase for std::unique_ptr<>:
class Base {
static constexpr int lifespan = 100;
int lifetime = lifespan;
public:
void reset() noexcept { lifetime = lifespan; }
}
struct Deleter {
void operator ()(Base* const b) const {
b->reset();
}
};
struct Particle : Base {
// ...
};
struct Pool {
std::unique_ptr<Particle, Deleter> create() {
// ...
}
}
int main() {
// ...
auto p1 = pool.create();
}
The solution to this really depends on the combination of
Why do you need to pool objects?
Why do objects need to have a default lifeTime of 100?
Why do objects need to change their lifeTime?
Why do existing objects obtained from the pool need to have their lifeTime reset to 100.
You have partially answered the first, although I'll bet your stated goal of improving performance is not based on anything other than "you think you need to improve performance". Really, such a goal should be based on measured performance being insufficient, otherwise it is no more than premature optimisation.
In any event, if I assume for sake of discussion that all of my questions above have good answers, I would do the following;
class Particle
{
public:
// member functions that provide functions used by `main()`.
private: // note all the members below are private
Particle();
void reset()
{
lifeTime=100;
};
friend class Pool;
};
class Pool
{
public:
Particle *create()
{
Particle *p;
// obtain an object for p to point at
// that may mean release it from some "pool" or creating a new one
p->reset();
return p;
};
void give_back(Particle *&p)
{
// move the value of p back into whatever the "pool" is
p = NULL; // so the caller has some indication it should not use the object
};
};
int main()
{
// presumably pool is created somehow and visible here
auto* p1=pool.create();
// do things with p1
pool.give_back(p1); // we're done with p1
auto *p2 = pool.create();
// p2 might or might not point at what was previously p1
}
Note that the value 100 only ever appears in the reset() function.
The reason for making constructors private and Pool a friend is to prevent accidental creation of new objects (i.e. to force use of the pool).
Optionally, making Particle::reset() be public allows main() to call p1->reset(), but that is not required. However, all objects when obtained from the pool (whether created fresh or reused) will be reset.
I'd probably also make use of std::unique_ptr<Particle> so the lifetime of objects is properly managed, for example, if you forget to give the object back to the pool. I'll leave implementing that sort of thing as an exercise.
I need to have access to an object which is implemented in a different concrete class. So I decided to use std::shared_ptr. I would like to know whether usage of std::shared_ptr is appropriate here, if not please suggest whether I should go with std::weak_ptr. So far I have been using raw pointers but now I decided to use smart pointers in my project, But I'm unable to decide which one should I use here. The following code snippet is analogous to what I'm trying to do in my project.
#include <iostream>
#include <memory>
class data
{
public:
data()
{
std::cout<<"\n data constructor Called"<<std::endl;
}
~data()
{
std::cout<<"\n data destructor Called"<<std::endl;
}
int GetData()
{
return val;
}
void SetData(int & val)
{
this->val = val;
}
private:
int val;
};
class sample
{
public:
sample();
~sample();
void GetShared(std::shared_ptr<data> & arg);
std::shared_ptr<data> sPtr;
};
sample::sample()
{
sPtr = std::make_shared<data>();
}
sample::~sample()
{
}
void sample::GetShared(std::shared_ptr<data> & arg)
{
arg = sPtr;
}
int main()
{
int val = 40;
sample obj;
{
std::shared_ptr<data> temp1;
obj.GetShared(temp1);
temp1->SetData(val);
std::cout<<"\n Data : "<<temp1->GetData()<<std::endl;
} // Just to understand whether pointer gets deleted if temp1 goes out of scope.
{
std::shared_ptr<data> temp2;
obj.GetShared(temp2);
val = 20;
temp2->SetData(val);
std::cout<<"\n Data : "<<temp2->GetData()<<std::endl;
}
return 0;
}
You would use shared_pointer to share ownership of some resource, when you don't have a clear owner of that resource.
Here it would be useful if you don't know if obj goes out of scope before temp1 and temp2 is done with the data. However, in this example it is clear that obj and the data object it holds will outlive the user. In that case you could just as well return a normal pointer, or perhaps a reference to the data.
Using a shared_pointer (or a weak_pointer) doesn't buy you anything, except added complexity.
In your code
sample obj;
{
std::shared_ptr<data> temp1;
obj.GetShared(temp1);
temp1->SetData(val);
std::cout<<"\n Data : "<<temp1->GetData()<<std::endl;
} // Just to understand whether pointer gets deleted if temp1 goes out of scope.
The data will not get deleted, because it is pointing to something that is held by obj, which is still alive.
I think the answer should depend on whether a data object can live after its corresponding sample object died:
If yes, then it should return a std::shared_ptr.
If not, then it should return a std::weak_ptr.
The difference between shared_ptr and weak_ptr is that weak_ptr does not increase the ref count on the object and does prevent the object from being deleted.
This has its pros and cons, if you perform async operations after you obtain the pointer and are unsure whether the object that provided the data has been destroyed then you can use weak_ptr and check if you still have access to the object.
If not then keep it simple and use shared_ptr.
You have two questions you need to ask yourself.
1) Will the calling object that gets the pointer from sample outlive the sample object?
If not then sample should use a std::unique_ptr and return a raw pointer or a reference.
2) If the calling object does outlive the sample object, does it mind if the data object gets destroyed before it does?
If not then return a std::weak_ptr that can be used to test if the data object is still alive before using it.
Otherwise return a std::shared_ptr to guarantee the data object lives as long as the calling object.
Summary:
If the calling object will not outlive the sample object:
class sample
{
std::unique_ptr<data> ptr; // UNIQUE (not shared)
public:
data* GetData() { return ptr.get(); }
};
If the calling object may outlive the sample object but doesn't care if the data object lives as long as it does:
class sample
{
std::shared_ptr<data> ptr;
public:
std::weak_ptr<data> GetData() { return ptr; }
};
If the calling object may outlive the sample object and needs to data object to keep living too:
class sample
{
std::shared_ptr<data> ptr;
public:
std::shared_ptr<data> GetData() { return ptr; }
};
My code is auto generated during compile time, so I don't know which object will be created.
During run time I have to decide whether I need it or not,so I want to creating object only if some condition satisfied, otherwise don't create and object below is example
class A {
public:
A(int type, int value):
type_(type),value_(value) {
if (type_ == 0) {
/*Create an object of this class and put in array */
} else {
/*Don't create an object of this class*/
}
}
private:
int type_;
int value_;
}
A a1(0,100); // Create an object
A a2(1,200); // Don't create an object
A a3(0,300); // Create an object
int main()
{
....
....
// use the object that was create and present in array
}
Inside the constructors body it's too late, the instance is already created then.
Either throw an exception, or use a template and sfinae to apply the restrictions at compile time.
Even better outsource the instances creation to a separate factory class, that acts on the condition. It can return a nullptr or otherwise empty smart pointer, to indicate the instance wasn't created.
The only way you can create this is from a static function. I would never use it like that, but if you really need it, you can do something like this.
class A {
public:
static A* createAnObject(int type, int value)
{
if (type == 0)
return new A(type, value);
else
return NULL;
}
~A();
private:
//Put constructur here so that will force programer to use your static function
A(int type, int value):type_(type),value_(value){};
int type_;
int value_;
}
};
A* a1 = A::createAnObject(0,100); // Create an object
A* a2 = A::createAnObject(1,200); // Don't create an object
A* a3 = A::createAnObject(0,300); // Create an object
int main()
{
//Now you need always to verify if you pointer is not NULL before use it
if(a1)
a1->somefunction();
....
}
But I do not recommend this way, creating object with new force you to always delete them by yourself and if you are a new programmer sometimes you will forget that, and if you have a NULL pointer so sometimes you will not verify it and try to call a function and this will crash you application.
I need to grab an object by reference and I used to do it like so:
MyObject& obj = FactoryThatGivesAnObject();
obj.MethodThatModifieObj();
No I need to do it based on a conditional:
MyObject obj;
// Need obj to be a reference to the returned values below
if( foo )
obj = FactoryThatGivesAnObject();
else
obj = OtherFactoryThatGivesAnObject();
obj.MethodThatModifiesObj();
How can I have obj be a reference in the second example?
References, unlike pointers, can only be set once. This is a useful feature many times, but this is the one frustrating aspect about it. You only want to set the reference once, but possibly to different things.
You have two options.
1) Use the ternary operator
This is often the easiest, if you're only dealing with two factories, and a simple boolean to decide which to use:
MyObject& obj = ( foo
? FactoryThatGivesAnObject();
: OtherFactoryThatGivesAnObject() );
However, if foo is more complicated, or if you have multiple factory options, the next option may be cleaner.
2) Use a factory method of your own
MyObject& get_an_object(const int state) // or whatever parameters you need
{
switch(state)
{
case USE_LEGACY_FACTORY: return FactoryThatGivesAnObject();
case USE_FOO_FACTORY: return OtherFactoryThatGivesAnObject();
case DO_SOMETHING_ELSE: return YetAnotherObjectFactory();
}
throw std::runtime_error("Bad Factory Selector");
}
// usage is simpler now
MyObject& obj = get_an_object(foo);
Note that you may need to pass several parameters to your factory method:
selection criteria. Your example was just foo - a simple boolean. As things grow, you may need additional criteria to help determine which factory to use.
factory objects. You may have factory objects instead of factory methods, in which case you need to pass references to those objects into your method.
One solution may be to use a ternary operator:
obj = foo ? FactoryThatGivesAnObject() : OtherFactoryThatGivesAnObject();
You could also use a pointer:
MyObject* pobj;
if( foo )
pobj = &FactoryThatGivesAnObject();
else
pobj = &OtherFactoryThatGivesAnObject();
Your very first line is shady:
MyObject& obj = FactoryThatGivesAnObject();
How is that supposed to work? The factory method cannot return a reference to a temporary, so the only sensible reference it could return is to a dynamically created object - but now who is responsible for this object?
(Unless you are just returning a reference to an existing object, that is. But I'm assuming that your factory is genuinely creating new objects.)
This code is a memory-leak car crash; I don't see any way to write anything sensible like that. A far better way is to return the newly created object in a responsible container, e.g. a shared_ptr or a unique_ptr:
#include <memory>
std::unique_ptr<MyObject> FactoryFunction()
{
return std::unique_ptr<MyObject>(new MyObject(3,5,7));
}
That way, if nobody picks up the factory product, or if an exception occurs, the dynamically allocated object will get properly disposed of.
This also makes it trivial to assign different pointers depending on a conditional:
std::unique_ptr<MyObject> x;
if (...) { x = Factory1(); }
else if (...) { x = Factory2(a,b); }
else { x = Factory3(argc, argv); }
How can I have obj be a reference in the second example?
You can't. References are aliases; you can only create them by pointing them at something, and once you've pointed them, they cannot be reassigned.
You would probably be better off using something like a std::auto_ptr or std::unique_ptr here. Note that your factory would need to return the auto/unique_ptr though. If your factory is returning a reference I suspect you might be accidentially returning references to unnamed temporaries (unedefined behavior), but without seeing the factories' code it's difficult to tell.
Here's one solution which is not technically a factory, but solves the same problem -- providing new objects when you change parameters:
struct A
{
int a;
float x;
int c;
};
class ObjectCollection
{
public:
ObjectCollection() { m_a.c = 10; }
A &get_obj_a(int a, float x)
{
m_a.a = a;
m_a.x = x;
return m_a;
}
private:
A m_a;
};
This version has advantage that it does not pass around ownership to the object, but still you can create different kinds of objects with it. Two calls to get_obj_a() will cause problems though, it only works if you call get_obj_a() immediately before you need the object. Now the if statement can be put inside the factory function. Also here's another way to do it:
class DerivedFactory
{
public:
DerivedFactory(ObjectCollection1 &c, ObjectCollection2 &c2) : c(c),c2(c2) { }
Base &get_obj_a_or_b(bool b) {
if (b) return c.get_obj_a(10,11.0);
else return c2.get_obj_b(20.0,13.0);
}
private:
ObjectCollection1 &c;
ObjectCollection2 &c2;
};
I'm using a library which returns a reference to me.
I need to use this reference as class-attribute.
Not being able to initialize the attribute in constructor directly (the lib needs to be inited before), I thought about using a shared_ptr for lazy initialization:
#include <iostream>
#include <string>
#include <tr1/memory>
//This is library, cannot touch
std::string globalString = "TEST";
std::string& getStringReference()
{
return globalString;
}
//this is my class which uses the library
class Foo
{
public:
Foo() :
testString_( std::tr1::shared_ptr< std::string& >() )
{
//do some initialization of the library here...
//now init the shared_ptr
testString_.reset( getStringReference() );
}
std::string getString() const
{
return *testString_;
}
private:
std::tr1::shared_ptr< std::string& > testString_;
};
//and a main to be compilable and check if the above works...
int main()
{
Foo foo;
std::cout << foo.getString() << std::endl;
}
But unfortunately this does not work. g++ gives messages like this:
error: forming pointer to reference type ‘std::string&’
I tried some other ways to get the reference into the shared_ptr, but nothing works... Perhaps you could give me a hint.
Note:
- In "real-world" instead of std::string the datatype is a class without default constructor.
- For those who still wonder: The above is just a simplified example-code :)
UPDATE:
- While trying to apply the suggestions, I found out that contrary to the used std::string from example, my class has a private copy constructor. This means I'm not able to just copy the object into a new one.
If you are provided by a reference only, that means that you are not responsible for memory management, and that in turns means that you cannot use your own memory management. That is, you should not use any type of smart pointer to hold that object.
While you can obtain the address of the real object with the & operator, doing so will cause undefined behavior later on when your shared_ptr goes out of scope and tries to free the memory and the library itself tries to free the memory on it's own.
You simply cannot take the address of a reference.
You can however use shared_ptr<string> and initialize it with &getStringReference. But that will cause the shared_ptr to try to delete the string, causing it to fail since it was never allocated using new. To fix this, make a copy:
testString_.reset(new std::string(getStringReference()))
Even better, let your class just store the reference directly. The you don't need to bother about memory management at all:
class Foo
{
std::string& _testString;
// ...
}
You need to understand the semantics of references and of memory management.
What you probably want is a raw pointer in your class. I assume you can't use a reference because you do not know what object it will refer to until you make the function call so you want to do something like ref=getRef();
You have no way of automatically "protecting" your pointer against becoming "dangling", but do not think there is anything you can do to rectify this situation. You just have to look at the documentation as to how to use the reference/pointer properly.
You could consider using Boost.Optional, which support optional references. This way, you could lazy initialize your reference without taking ownership of the referenced object as you do by using shared_ptr:
#include <iostream>
#include <string>
#include <boost/optional.hpp>
//This is library, cannot touch
std::string globalString = "TEST";
std::string& getStringReference()
{
return globalString;
}
//this is my class which uses the library
class Foo
{
public:
Foo()
{
//do some initialization of the library here...
//now init the optional reference
testString_.reset( getStringReference() );
}
std::string getString() const
{
return *testString_;
}
private:
boost::optional< std::string& > testString_; //<-- note the use of optional
};
//and a main to be compilable and check if the above works...
int main()
{
Foo foo;
std::cout << foo.getString() << std::endl;
}
Stop using shared_ptr now. Sharing is not an unilateral decision.
That being said, you are returned a reference to an object, not the object proper. There are two things you can do:
copy the object, and therefore deciding to manage the lifetime of the copy yourself
take a reference to the object, and let it up to the library you called to manage the lifetime, in which case you'll need to have some knowledge about it
I would definitely recommend copying unless there is a reason not to, much easier to get it right.
If you go for copying, use boost::optional<LibObject> within your class, this way you'll bypass the initialization issue.
If you wish to use a reference, you can still use boost::optional, and it'll work too! Use it as such: boost::optional<LibObject&>, but make sure the object you have a reference to will live long enough.
Finally, regarding the initialization issue, you could use a function to process the initialization and return a reference directly, thus initializing the reference of your class in the initialization list.
You can not use a shared_ptr with a reference type, because a reference is just that - a reference to an object. It is not a real object.
Next example is just simplified version of what you tried to do :
int main()
{
int &* a;
}
Use a factory function?
class Library
{
public:
static void Init();
static LibraryThing & getThing();
};
class Foo
{
public:
static shared_ptr<Foo> Create()
{
if (!_libInit)
{
Library::Init();
_libInit = true;
}
return make_shared(new Foo(Library::getThing()));
}
private:
Foo(LibraryThing & ref) : _ref(ref)
{
}
private:
LibraryThing & _ref;
static bool _libInit;
};