1.) What is the difference between
CArray <SomeClass> collection;
and
CArray <SomeClass,SomeClass> collection;
or even
CArray <SomeClass* ,SomeClass* > collection;
?
2.) While reading some comments on Stackoverflow I came to a note saying "Don't use CArray". Why should CArray not be used?
This:
CArray <SomeClass> collection;
is equivalent to this:
CArray <SomeClass, const SomeClass&> collection;
The second template parameter is used to specify the type through which members are accessed. The template parameters are described in the documentation on MSDN.
This:
CArray <SomeClass* ,SomeClass* > collection;
stores a collection of pointers to objects of type SomeClass, whereas the other two store collections of objects of type SomeClass.
As for why you "shouldn't use it," std::vector, which is part of the C++ language standard, and thus portable, is probably a better choice for most projects. If you have legacy code that uses CArray, then you may need to use it, and there's nothing wrong with that.
The difference is what is stored in the CArray object and how it is stored in the object, whether the CArray elements are objects or pointers to objects of some class.
CArray seems to have a few unexpected behaviors. It has been around for a long time and was designed to fit into the MFC ecosystem. The C++ Standard Template Library vector has much nicer and more generic characteristics especially when dealing with objects other than simple data types.
My experience has been with using CList and CArray with pointers to objects. Doing this they seem to be more predictable though you do need to worry about managing memory.
One issue from looking at the source in afxtempl.h is that when the CArray is made larger through the internal function SetSize(), a memcpy_s() function is used to copy CArray elements from one memory area to another. So you need to be careful about pointers and shallow copying of CArray elements. And since memcpy_s() is used rather than memmove_s() if you are doing something funky with over lapped memory areas, there may be an issue.
This may be why my experience with CArray as a container for pointers to objects seems to work much better.
The interesting thing is it looks like the Append() and Copy() methods use an internal function CopyElements() which performs an element by element assignment and not a memcpy_s() function call. However these methods are used with CArray objects and not with the individual elements.
CArray is derived from CObject which means that the data structure will have all the baggage of CObject. However there are also some good things that CObject brings along in the MFC world like serialization.
It looks like you should use a reference as the second template argument so you should use CArray <SomeClass, SomeClass &> collection; if you are using a class. I ran into problems when I did not do this until I discovered the section Creating an Array List from MFC Collections: The CArray Class.
2) Since CArray reallocates memory when new element is added.
Related
I am trying to use boost::singleton_pool to create a large number of objects of a type 'Order' in a highly performance critical multithreaded application. Looking at the documentation, this is what I should be doing,
struct OrderTag{};
typedef boost::singleton_pool<OrderTag, sizeof(Order)> OrderPool;
boost::singleton_pool has a static member function malloc which returns pointer of the void*, but I need to create objects of the type Order in OrderPool by making calls to its constructor. Shall I be using boost::pool_allocator along with singleton_pool to do so?
Thanks.
In short: no. boost::pool_allocator implementation itself uses boost::singleton_pool and provides interface like std::allocator so you can use it with STL containers (but not only STL and not only containers) like vector, list etc. The UserAllocator concept is not something like boost::pool_allocator but it's a thing that controls memory management at the lowest level. For example I wrote UserAllocator that allocates memory via mmap() function and not uses heap at all.
So to create objects of a type 'Order' you should use boost::pool_allocator or boost::fast_pool_allocator. In your case it is not necessary to use boost::singleton_pool directly.
You can use singleton_pool with placement new like this:
Order* p = new (OrderPool.malloc()) Order(/* add ctor parameters if any*/);
or use boost::object_pool<Order>
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'd like to use a std::vector to control a given piece of memory. First of all I'm pretty sure this isn't good practice, but curiosity has the better of me and I'd like to know how to do this anyway.
The problem I have is a method like this:
vector<float> getRow(unsigned long rowIndex)
{
float* row = _m->getRow(rowIndex); // row is now a piece of memory (of a known size) that I control
vector<float> returnValue(row, row+_m->cols()); // construct a new vec from this data
delete [] row; // delete the original memory
return returnValue; // return the new vector
}
_m is a DLL interface class which returns an array of float which is the callers responsibility to delete. So I'd like to wrap this in a vector and return that to the user.... but this implementation allocates new memory for the vector, copies it, and then deletes the returned memory, then returns the vector.
What I'd like to do is to straight up tell the new vector that it has full control over this block of memory so when it gets deleted that memory gets cleaned up.
UPDATE: The original motivation for this (memory returned from a DLL) has been fairly firmly squashed by a number of responders :) However, I'd love to know the answer to the question anyway... Is there a way to construct a std::vector using a given chunk of pre-allocated memory T* array, and the size of this memory?
The obvious answer is to use a custom allocator, however you might find that is really quite a heavyweight solution for what you need. If you want to do it, the simplest way is to take the allocator defined (as the default scond template argument to vector<>) by the implementation, copy that and make it work as required.
Another solution might be to define a template specialisation of vector, define as much of the interface as you actually need and implement the memory customisation.
Finally, how about defining your own container with a conforming STL interface, defining random access iterators etc. This might be quite easy given that underlying array will map nicely to vector<>, and pointers into it will map to iterators.
Comment on UPDATE: "Is there a way to construct a std::vector using a given chunk of pre-allocated memory T* array, and the size of this memory?"
Surely the simple answer here is "No". Provided you want the result to be a vector<>, then it has to support growing as required, such as through the reserve() method, and that will not be possible for a given fixed allocation. So the real question is really: what exactly do you want to achieve? Something that can be used like vector<>, or something that really does have to in some sense be a vector, and if so, what is that sense?
Vector's default allocator doesn't provide this type of access to its internals. You could do it with your own allocator (vector's second template parameter), but that would change the type of the vector.
It would be much easier if you could write directly into the vector:
vector<float> getRow(unsigned long rowIndex) {
vector<float> row (_m->cols());
_m->getRow(rowIndex, &row[0]); // writes _m->cols() values into &row[0]
return row;
}
Note that &row[0] is a float* and it is guaranteed for vector to store items contiguously.
The most important thing to know here is that different DLL/Modules have different Heaps. This means that any memory that is allocated from a DLL needs to be deleted from that DLL (it's not just a matter of compiler version or delete vs delete[] or whatever). DO NOT PASS MEMORY MANAGEMENT RESPONSIBILITY ACROSS A DLL BOUNDARY. This includes creating a std::vector in a dll and returning it. But it also includes passing a std::vector to the DLL to be filled by the DLL; such an operation is unsafe since you don't know for sure that the std::vector will not try a resize of some kind while it is being filled with values.
There are two options:
Define your own allocator for the std::vector class that uses an allocation function that is guaranteed to reside in the DLL/Module from which the vector was created. This can easily be done with dynamic binding (that is, make the allocator class call some virtual function). Since dynamic binding will look-up in the vtable for the function call, it is guaranteed that it will fall in the code from the DLL/Module that originally created it.
Don't pass the vector object to or from the DLL. You can use, for example, a function getRowBegin() and getRowEnd() that return iterators (i.e. pointers) in the row array (if it is contiguous), and let the user std::copy that into its own, local std::vector object. You could also do it the other way around, pass the iterators begin() and end() to a function like fillRowInto(begin, end).
This problem is very real, although many people neglect it without knowing. Don't underestimate it. I have personally suffered silent bugs related to this issue and it wasn't pretty! It took me months to resolve it.
I have checked in the source code, and boost::shared_ptr and boost::shared_array use dynamic binding (first option above) to deal with this.. however, they are not guaranteed to be binary compatible. Still, this could be a slightly better option (usually binary compatibility is a much lesser problem than memory management across modules).
Your best bet is probably a std::vector<shared_ptr<MatrixCelType>>.
Lots more details in this thread.
If you're trying to change where/how the vector allocates/reallocates/deallocates memory, the allocator template parameter of the vector class is what you're looking for.
If you're simply trying to avoid the overhead of construction, copy construction, assignment, and destruction, then allow the user to instantiate the vector, then pass it to your function by reference. The user is then responsible for construction and destruction.
It sounds like what you're looking for is a form of smart pointer. One that deletes what it points to when it's destroyed. Look into the Boost libraries or roll your own in that case.
The Boost.SmartPtr library contains a whole lot of interesting classes, some of which are dedicated to handle arrays.
For example, behold scoped_array:
int main(int argc, char* argv[])
{
boost::scoped_array<float> array(_m->getRow(atoi(argv[1])));
return 0;
}
The issue, of course, is that scoped_array cannot be copied, so if you really want a std::vector<float>, #Fred Nurk's is probably the best you can get.
In the ideal case you'd want the equivalent to unique_ptr but in array form, however I don't think it's part of the standard.
Is it possible to have a vector without specializing it?
My problem is: I have an abstract class N4GestureRecognizer
and a couple of subclasses of it.
So in a Controller class I want to have a vector<N4GestureRecognizer> recognizers_ but since it is abstract I cannot.
How can I store this recognizers in a vector or collection or list or whatever is loop-able in standard c++?
Store them as pointers. Either pure pointers or some smart pointer class.
EXTRA
Actually, pointers are the only way even if the class is not abstracts, but is subclassed and child classes are intended to be used in the vector. Why: std::vector allocates sizeof(T) bytes for each element, but sizeof(derivedFromT) could be bigger than sizeof(T). You will be able to push a child object into the vector, but it can cause unpredictable issues at run time.
Managing vectors of pointers is a pain, of course, but as far as I remember, boost contains some smart pointers to simplify the task.
What you need is a std::vector< std::shared_ptr<N4GestureRecognizer> >.
If your std lib comes without std::shared_ptr (it's part of the next C++ standard, expected to be published next year), it might come with std::tr1::shared_ptr, which is the same (as a addition to the current C++ standard by the official Technical Report 1). If that also fails, there's always boost, which has boost:shared_ptr (which is the predecessor of std::tr1::shared_ptr and std::shared_ptr).
Note: Don't use naked pointers (std::vector<N4GestureRecognizer*>). There's almost no way to make this safe so that it doesn't leak.
I am seeking to improve my C++ skills by writing a sample software renderer. It takes objects consisting of points in a 3d space and maps them to a 2d viewport and draws circles of varying size for each point in view. Which is better:
class World{
vector<ObjectBaseClass> object_list;
public:
void generate(){
object_list.clear();
object_list.push_back(DerivedClass1());
object_list.push_back(DerivedClass2());
or...
class World{
vector<ObjectBaseClass*> object_list;
public:
void generate(){
object_list.clear();
object_list.push_back(new DerivedClass1());
object_list.push_back(new DerivedClass2());
?? Would be using pointers in the 2nd example to create new objects defeat the point of using vectors, because vectors automatically call the DerivedClass destructors in the first example but not in the 2nd? Are pointers to new objects necessary when using vectors because they handle memory management themselves as long as you use their access methods? Now let's say I have another method in world:
void drawfrom(Viewport& view){
for (unsigned int i=0;i<object_list.size();++i){
object_list.at(i).draw(view);
}
}
When called this will run the draw method for every object in the world list. Let's say I want derived classes to be able to have their own versions of draw(). Would the list need to be of pointers then in order to use the method selector (->) ?
Since you are explicitly stating you want to improve your C++, I am going to recommend you start using Boost. This can help you with your problem in three different ways:
Using a shared_ptr
Using a shared_ptr could declare your vector like this:
std::vector< boost::shared_ptr< ObjectBase > > object_list;
And use it like this:
typedef std::vector< boost::shared_ptr< ObjectBase > >::iterator ObjectIterator;
for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
(*it)->draw(view);
This would give you polymorphism and would be used just like it was a normal vector of pointers, but the shared_ptr would do the memory-management for you, destroying the object when the last shared_ptr referencing it is destroyed.
Note about C++11: In C++11 shared_ptr became part of the standard as std::shared_ptr, so Boost is no longer required for this approach. However, unless you really need shared ownership, it is recommended you use std::unique_ptr, which was newly introduced in C++11.
Using a ptr_vector
Using a ptr_vector you would do it like this:
boost::ptr_vector< ObjectBase > object_list;
And use it like this:
typedef boost::ptr_vector< ObjectBase >::iterator ObjectIterator;
for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
(*it)->draw(view);
This would again be used like a normal vector of pointers, but this time the ptr_vector manages the lifetime of your objects. The difference to the first approach is, that here your objects get destroyed when the vector gets destroyed, whereas above they may live longer than the container, if other shared_ptrs referencing them exist.
Using a reference_wrapper
Using a reference_wrapper you would declare it like this:
std::vector< boost::reference_wrapper< ObjectBase > > object_list;
And then use it like this:
typedef std::vector< boost::reference_wrapper< ObjectBase > >::iterator
ObjectIterator;
for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
it->draw(view);
Notice that you do not have to dereference the iterator first as in the above approaches. This does however only work if the lifetime of your objects is managed elsewhere and is guaranteed to be longer than that of the vector.
Note about C++11: reference_wrapper has also been standardized in C++11 and is now usable as std::reference_wrapper without Boost.
As pointed out in Maciej Hs answer, your first approach results in object slicing. In general you may want to look into iterators when using containers.
You wont get what You want with this code
class World{
vector<ObjectBaseClass> object_list;
public:
void generate(){
object_list.clear();
object_list.push_back(DerivedClass1());
object_list.push_back(DerivedClass2());
What is going to happen is called object slicing. You will get a vector of ObjectBaseClass.
To make polymorphism work You have to use some kind of pointers. There are probably some smart pointers or references in boost or other libraries that can be used and make the code much safer than the second proposed solution.
As for your first question, it is generally preferred to use automatically allocated objects rather than dynamically allocated objects (in other words, not to store pointers) so long as for the type in question, copy-construction and assignment is possible and not prohibitively expensive.
If the objects can't be copied or assigned, then you can't put them directly into a std::vector anyway, and so the question is moot. If the copying and/or assignment operations are expensive (e.g. the object stores a large amount of data), then you might want to store pointers for efficiency reasons. Otherwise, it is generally better not to store pointers for exactly the reason that you mentioned (automatic deallocation)
As for your second question, yes, that is another valid reason to store pointers. Dynamic dispatch (virtual method calls) work only on pointers and references (and you can't store references in a std::vector). If you need to store objects of multiple polymorphic types in the same vector, you must store pointers in order to avoid slicing.
Well, it depends on what you are trying to do with your vector.
If you don't use pointers, then it is a copy of the object you pass in that gets put on the vector. If it is a simple object, and/or you don't want to bother with keeping track of the storage for them, this may be exactly what you want. If it is something complex, or very time-consuming to construct and destruct, you might prefer to do that work only once each and pass pointers into the vector.