ok, so I got a doubt, I want to know if this is possible:
I'm using a database, with generic data (strings, ints, bools, etc...). Whenever an object is constructed or a member of an object is modified, I have to query the database with the specific action (SELECT or UPDATE).
First of all, this isn't a DB related question, my real problem is that I have a ptr_vector which holds boost::any's pointers to members of the object. In code something like this:
class Enemy{
private:
//some private data...
public:
auto_ptr<int> ID_Enemy;
auto_ptr<string> Enemy_Name;
//miscellaneous methods...
};
then I pass the members I want to modify to a function of another miscellaneous class which takes as argument a boost::any*:
misc_class.addValues((boost::any*)(ID_Enemy.get()));
misc_class.addValues((boost::any*)(Enemy_Name.get()));
that same class accepts the any*, and does the following:
auto_ptr<boost::any> val2(val); //being val, the passed any*
Enemy_Values.push_back(val2);
Enemy_Values is a ptr_vector. So when I access this misc_class which has Enemy_Values as member, I want to change the value to which an auto_ptr inside is pointing:
misc_class.Enemy_Values[0] = (boost::any)(69);
And here, I get a violation error. I've tried many things, and someone told me that I shouldn't be using containers of auto_ptr or converting back and forth with boost::any. Is this that I am doing possible, or there is a better and more intuitive way?
Thanks in advance.
(boost::any*)(ID_Enemy.get()) performs a reinterpret_cast since you are casting unrelated pointer types. This means you get an invalid pointer to an any, pointing to what is really an integer.
Instead, construct a temporary boost::any object and pass it by reference to addValues:
misc_class.addValues(boost::any(ID_Enemy.get());
Your use of auto_ptr is in fact incorrect: auto_ptr deletes objects on the freestore but here we're dealing with locals instead. addValues merely needs to push the value of the any object into the vector:
Enemy_Values.push_back(val);
... and Enemy_Values should just be a std::vector.
You could do this with a ptr_vector and freestore-allocated boost::any objects, but that would be more complicated than necessary.
auto_ptr has a number of problems. Since you are already using boost, why not use boost::shared_ptr instead?
Related
Simply written I would like to ask "what is a good reason to use smart pointers?"
for ex std::unique_ptr
However, I am not asking for reasons to use smart pointers over regular (dumb) pointers. I think every body knows that or a quick search can find the reason.
What I am asking is a comparison of these two cases:
Given a class (or a struct) named MyObject use
std:queue<std::unique_ptr<MyObject>>queue;
rather than
std:queue<MyObject> queue;
(it can be any container, not necessarily a queue)
Why should someone use option 1 rather than 2?
That is actually a good question.
There are a few reasons I can think of:
Polymorphism works only with references and pointers, not with value types. So if you want to hold derived objects in a container you can't have std::queue<MyObject>. One options is unique_ptr, another is reference_wrapper
the contained objects are referenced (*) from outside of the container. Depending on the container, the elements it holds can move, invalidating previous references to it. For instance std::vector::insert or the move of the container itself. In this case std::unique_ptr<MyObject> assures that the reference is valid, regardless of what the container does with it (ofc, as long as the unique_ptr is alive).
In the following example in Objects you can add a bunch of objects in a queue. However two of those objects can be special and you can access those two at any time.
struct MyObject { MyObject(int); };
struct Objects
{
std::queue<std::unique_ptr<MyObject>> all_objects_;
MyObject* special_object_ = nullptr;
MyObject* secondary_special_object_ = nullptr;
void AddObject(int i)
{
all_objects_.emplace(std::make_unique<MyObject>(i));
}
void AddSpecialObject(int i)
{
auto& emplaced = all_objects_.emplace(std::make_unique<MyObject>(i));
special_object_ = emplaced.get();
}
void AddSecondarySpecialObject(int i)
{
auto& emplaced = all_objects_.emplace(std::make_unique<MyObject>(i));
secondary_special_object_ = emplaced.get();
}
};
(*) I use "reference" here with its english meaning, not the C++ type. Any way to refer to an object (e.g. via a raw pointer)
Usecase: You want to store something in a std::vector with constant indices, while at the same time being able to remove objects from that vector.
If you use pointers, you can delete a pointed to object and set vector[i] = nullptr, (and also check for it later) which is something you cannot do when storing objects themselves. If you'd store Objects you would have to keep the instance in the vector and use a flag bool valid or something, because if you'd delete an object from a vector all indices after that object's index change by -1.
Note: As mentioned in a comment to this answer, the same can be archieved using std::optional, if you have access to C++17 or later.
The first declaration generates a container with pointer elements and the second one generates pure objects.
Here are some benefits of using pointers over objects:
They allow you to create dynamically sized data structures.
They allow you to manipulate memory directly (such as when packing or
unpacking data from hardware devices.)
They allow object references(function or data objects)
They allow you to manipulate an object(through an API) without needing to know the details of the object(other than the API.)
(raw) pointers are usually well matched to CPU registers, which makes dereferencing a value via a pointer efficient. (C++ “smart” pointers are more complicated data objects.)
Also, polymorphism is considered as one of the important features of Object-Oriented Programming.
In C++ polymorphism is mainly divided into two types:
Compile-time Polymorphism
This type of polymorphism is achieved by function overloading or operator overloading.
Runtime Polymorphism
This type of polymorphism is achieved by Function Overriding which if we want to use the base class to use these functions, it is necessary to use pointers instead of objects.
I think it'll be better if I show my code first, then explain my problem.
std::map<std::string, SManager> m_managers;
//SResourceManager is derived from SManager
SResourceManager& getResourceManager() { return m_managers["resource_manager"]->second; }
What I'm trying to do is return a reference from a SManager (which would be the copy of SResourceManager) to be able to use elsewhere. I know I can use things like std::shared_ptr, but I'd prefer not to use pointers in this situation because I want the SResourceManager within the map to possibly change, but stay in there. Is there a way to cast this to a value that I can actually return?
Thanks
"SResourceManager is derived from SManager". Going from a base type to a derived type will require an explicit cast.
However, you have a bigger problem. Your map contains SManager objects directly. As a consequence it does not and can never contain SResourceManager objects or any other derived type. Whatever code you've written to populate that map is most likely ending up slicing off the derived portions.
If you want to have things in terms of a base type that could actually refer to objects of derived types then you need to use pointers in some manner. unique_ptr or shared_ptr are reasonable options.
So you might end up with something like:
std::map<std::string, std::unique_ptr<SManager>> m_managers;
SResourceManager& getResourceManager() { return *static_cast<SResourceManager*>(m_managers["resource_manager"].get()); }
It looks like you are using incorrect syntax. If to suppose that type SManager is declared as pointer to a polymorphic class then the function will look the following way
SResourceManager& getResourceManager() { return *m_managers["resource_manager"]; }
I am wondering what might be the best way to accomplish a design dilemma in C++ ...
I have a class, which contains member variables of type Base of another class, and the real objects that are created are created as Derived of Base.
The class does not need to modify these variables, it is only using them. Someone else is creating these variables. These Derived classes also need to go to container (std::vector, QList, etc) classes in my class, so they should perform proper copy construction and assignment.
So, I was wondering what might be the best:
Create the member variables as a Base* and let us manage them and the memory they use. This leads to the classical memory leak issues... Someone just forgets to delete the object when they are not using it anymore.
Create the member variables as a Base& and let's pray that they do not disappear when they go out of scope somewhere.
Having reference member variables is always a poor choice because the compiler generated assignment and move assignment do the wrong thing, or not what one would expect.
Stick to pointers or smart pointers for member variables.
#hansmaad is just right, if you have a problem in controlling life time of the object you should share its ownership with those who create or manage it.
You have 2 options:
1) boost::shared_ptr or std::tr1::shared_ptr
You can easily use this class for any type Base without changing Base, but if you are working in a multi threaded environment it is very hard to achieve thread safety for shared_ptr and do not forget if you create an object as shared using one of this classes you should not manage the life time of the object directly and it is not legal to create a new shared object from raw pointer and you should always copy construct shared object. for example:
boost::shared_ptr<Base> sharedObject( new Drived() );
boost::shared_ptr<Base> validCopy( sharedObject ); // Ok share ownership
Base* p = sharedObject.get();
boost::shared_ptr<Base> invalidCopy( p ); // Error, can't create new shared_ptr from raw pointer
2) boost::intrusive_ptr
You can easily make it thread safe and you can pass it as either raw pointer or smart pointer since it can constructed from raw pointer because reference counting is implemented in the class instead but you should change definition of the class and add you reference counting mechanism
I would go with pointers, both for your vectors (i.e., vector<Base *>, not vector<Base>) and your container class for the following reasons:
If you store the Derived objects in a vector, that vector may get re-sized, which causes all the objects to 'move' to new locations in memory. This would invalidate all outstanding pointers and references
If your container contains references, you are not able to copy it as easily as you would if it contains pointers, as references can only be bound when defined (so in the constructor via MyClass::MyClass(int &a) : memberA(a) {}, if memory serves)
Pointers can be changed via other means such as set methods as needed, and can be set to null in the event of an absence of information
As far as ownership goes, jrok was the first to say it: shared_ptr<> is your friend. Don't reinvent the wheel, just make use of the standard library to simplify things for you. The only thing you would need to worry about in that case is circular pointers (i.e., the object points to itself, so there is always a valid pointer).
The first thing to consider with reference member variables is whether your class (not Derived, the class that's going to have a data member that is a pointer or a reference to Base) needs value semantics (which is another way of saying, "copies and assigns properly").
If so, then reference member variables are more or less out of the question straight away, because they can't be reseated. There are some odd situations where you can use them anyway, but you might as well assume that you won't, and use pointers.
Reference data members are occasionally useful for types that have "entity semantics" (that is, they don't assign at all and may or may not copy), but still they don't gain you a great deal. They can also lure you into the error of writing a constructor that takes a const Base& parameter, and storing it in a reference data member[*].
Who owns the object (and is responsible for freeing it) is completely independent of whether you use a pointer or a reference. There's probably a general convention not to use references for things you own (and there should be a convention not to use raw pointers for things you own, you should choose or write a suitable smart pointer. Smart pointer classes can hold a raw pointer). But that is just convention. You shouldn't assume that you manage the memory if and only if you have a pointer.
Summary: use a pointer, then make a separate decision how the memory is managed.
[*] This is a mistake, because eventually someone will accidentally use a temporary object in an initializer, and then the instance of your class with its reference data member will outlive the temporary. For this reason, things that store references for use after they return shouldn't take const & parameters, even if they don't modify the object. They can take const * instead. In C++11 I suppose they might be OK if there is also an rvalue reference overload, to prevent the const& overload being selected for temporaries, but it's not something I've tried out yet.
You should think about ownership. Whe owns that objects? If there is no clear answer to this questions, you should use a std::shared_ptr<Base> (shared ownership). If there is one class that owns that objects and all others just use them, you could use a std::unique_ptr<Base>, a pointer container like boost::ptr_vector or if there is no polymorphism it that owning classes just the concrete instance. In all other classes you can use plain pointers (prefered as class members) or references (prefered as arguments, if null is not allowed) to that objects.
Case 1 - Shared ownership
class IWorkOnBaseObjects
{
std::vector<std::shared_ptr<Base>> mySubset;
};
class MeToo
{
std::shared_ptr<Base> iNeedThisOne;
};
Case 2
class HomeOfBaseObjects
{
std::vector<std::uniqe_ptr<Base>> baseObjects;
};
class IWorkOnBaseObjects
{
std::vector<Base*> mySubset;
};
Case 3
class A : public Base{};
class B : public Base{};
class HomeOfAObjects
{
std::vector<A> aObjects;
};
class HomeOfBObjects
{
std::vector<B> bObjects;
};
class INeedABaseObject
{
Base* thisOne;
};
Is it possible to store a bunch of objects by their base class in say an std::list without pointers. I would really like the objects to be held in the container, then retrieve a pointer to the object in the container and dynamic_cast it to correct derived class.
I have it working fine using pointers. Like (super simple version):
class IComponent
{
virtual ~Icomponent(){}
}
class PositionComponent: public IComponent
{
//...
float x, y;
}
std::list<IComponent*> CList;
//...
// fill the list
// put reference to object in pComponent
//...
PositionComponent* position = dynamic_cast<PositionComponent*>( pComponent)
position->x = 346452.235612;
But the memory management is a huge pain. My actual structure is a
map<enumValue, map<int, IComponent*> >
I get the feeling I can't use the objects themselves because when I add any derived component into the list the extra data will be cut off and leave me with the base class only. This didn't figure this until I tried static_cast instead and it crashed.
Can answer my original question and/or confirm my feelings on the matter. Thanks!
to minimize pain of manual memory management use smart pointers: std::unique_ptr if your compiler already supports it or boost::shared_ptr, but not std::auto_ptr that is not supposed to be used in containers
As you guessed, when you stored an object in a container by value, it gets sliced and the data is chopped off.
If you only need to store one data type (you only show one in your code), then you can make the container hold that type.
If not, you really are stuck using pointers. You can make the memory management much easier by using a smart pointer, or if appropriate, a boost ptr_container of some sort.
Further you might want to think if you need to spend one more iteration considering your design to provide an interface that doesn't require doing a dynamic_cast to get the original type back out again.
Is it possible to store a bunch of objects by their base class in say
an std::list without pointers.
This sentence seems to be contrdicted in C++ point of view IMO. Because STL container can only hold same type of object, if you put derived object into a base type container, it got sliced.
So the apparent normal solution is to use container to hold base type pointers like you did(u could use boost/std smart pointer for memory management)
If you really want to store different objects in one STL container, you may want to consider use boost::any.
I came accross several questions where answers state that using T* is never the best idea.
While I already make much use of RIIC, there is one particular point in my code, where I use T*. Reading about several auto-pointers, I couldn't find one where I'd say that I have a clear advantage from using it.
My scenario:
class MyClass
{
...
// This map is huge and only used by MyClass and
// and several objects that are only used by MyClass as well.
HashMap<string, Id> _hugeIdMap;
...
void doSomething()
{
MyMapper mapper;
// Here is what I pass. The reason I can't pass a const-ref is
// that the mapper may possibly assign new IDs for keys not yet in the map.
mapper.setIdMap(&_hugeIdMap);
mapper.map(...);
}
}
MyMapper now has a HashMap<...>* member, which - according to highly voted answers in questions on unrelated problems - never is a good idea (Altough the mapper will go out of scope before the instance of MyClass does and hence I do not consider it too much of a problem. There's no new in the mapper and no delete will be needed).
So what is the best alternative in this particular use-case?
Personally I think a raw pointer (or reference) is okay here. Smart pointers are concerned with managing the lifetime of the object pointed to, and in this case MyMapper isn't managing the lifetime of that object, MyClass is. You also shouldn't have a smart pointer pointing to an object that was not dynamically allocated (which the hash map isn't in this case).
Personally, I'd use something like the following:
class MyMapper
{
public:
MyMapper(HashMap<string, Id> &map)
: _map(map)
{
}
private:
HashMap<string, Id> &_map
};
Note that this will prevent MyMapper from having an assignment operator, and it can only work if it's acceptable to pass the HashMap in the constructor; if that is a problem, I'd make the member a pointer (though I'd still pass the argument as a reference, and do _map(&map) in the initializer list).
If it's possible for MyMapper or any other class using the hash map to outlive MyClass, then you'd have to start thinking about smart pointers. In that case, I would probably recommend std::shared_ptr, but you'd have to use it everywhere: _hugeIdMap would have to be a shared_ptr to a dynamically allocated value, not a regular non-pointer field.
Update:
Since you said that using a reference is not acceptable due to the project's coding standards, I would suggest just sticking with a raw pointer for the reasons mentioned above.
Naked pointers (normally referred to as raw pointers) are just fine when the object has no responsibility to delete the object. In the case of MyMapper then the pointer points to an object already owned by MyClass and is therefore absolutely fine to not delete it. The problem arises when you use raw pointers when you do intend for objects to be deleted through them, which is where problems lie. People only ask questions when they have problems, which is why you almost always see it only used in a problematic context, but raw pointers in a non-owning context is fine.
How about passing it into the constructor and keeping a reference (or const-reference) to it? That way your intent of not owning the object is made clear.
Passing auto-pointers or shared-pointers are mostly for communicating ownership.
shared pointers indicate it's shared
auto-pointers indicate it's the receivers responsibility
references indicate it's the senders responsibility
blank pointers indicate nothing.
About your coding style:
our coding standards have a convention that says never pass non-const references.
Whether you use the C++ reference mechanism or the C++ pointer mechanism, you're passing a (English-meaning) reference to the internal storage that will change. I think your coding standard is trying to tell you not to do that at all, not so much that you can't use references to do so but that you can do it in another way.