Assume I have a following class, basically an ordinary array wrapper:
template<class T>
SimpleArray {
T * array;
SimpleArray(): T(NULL) {}
SimpleArray(T * array_) {
// what goes here?
}
// TODO: copy constructor and copy assignment
~SimpleArray() {
delete[] array;
}
};
How do I copy elements from one array to another? If it was a simple type, I could just use something like memcpy, and it would work just fine. But what if T is a complex type that requires deep copying? If, say, T has a member array, than shallow-copying it would create several T objects pointing to the same resource, which is a disaster.
Basically, I need some way to create a deep copy of an array. Any suggestions?
I know I could use something from the standard library, but there's a reason I don't. SimpleArray is designed to give an easy access to the internal storage of my objects in form of T*. As far as I am concerned, no STL container supports such functionality.
It's inadvisable to roll your own dynamic arrays. If all you need is access to the underlying data via a T*, then you can use vec.data() (c++11 only), or &vec.front().
Related
I want to ask whether there are some problems with the copy for the vector of pointer items. Do I need to strcpy or memcpy because there may be depth copy problem?
For instance:
Class B;
Class A
{
....
private:
std::vector<B*> bvec;
public:
void setB(std::vector<B*>& value)
{
this->bvec = value;
}
};
void main()
{
....
std::vector<const B*> value; // and already has values
A a;
a.setB(value);
}
This example only assign the value to the class variable bvec inside A class. Do I need to use memcpy since I found that std::vector bvec; has pointer items? I am confused with the depth copy in C++, could you make me clear about that? Thank you.
Think about this, if you remove and delete an item from the vector value after you call setB, then the vector in A will have a pointer that is no longer valid.
So either you need to do a "deep copy", have guarantees that the above scenario will never happen, or use shared smart pointers like std::shared_ptr instead of raw pointers. If you need pointers, I would recommend the last.
There is another alternative, and that is to store the vector in A as a reference to the real vector. However, this has other problems, like the real vector needs to be valid through the lifetime of the object. But here too you can use smart pointers, and allocate the vector dynamically.
It is unlikely you need strcpy or memcpy to solve your problem. However, I'm not sure what your problem is.
I will try to explain copying as it relates to std::vector.
When you assign bvev to value in setB you are making a deep copy. This means all of the elements in the vector are copied from value to bvec. If you have a vector of objects, each object is copied. If you have a vector of pointers, each pointer is copied.
Another option is to simply copy the pointer to the vector if you wish to reference the elements later on. Just be careful to manage the lifetimes properly!
I hope that helps!
You probably want to define your copy constructor for class A to ensure the problem your asking about is handled correctly (though not by using memcpy or strcpy). Always follow the rule of three here. I'm pretty sure with std::vector your good, but if not, then use a for loop instead of memcpy
I have a class Bullet that takes several arguments for its construction. However, I am using a dynamic memory array to store them. I am using C++ so i want to conform to it's standard by using the new operator to allocate the memory. The problem is that the new operator is asking for the constructor arguments when I'm allocating the array, which I don't have at that time. I can accomplish this using malloc to get the right size then fill in form there, but that's not what i want to use :) any ideas?
pBulletArray = (Bullet*) malloc(iBulletArraySize * sizeof(Bullet)); // Works
pBulletArray = new Bullet[iBulletArraySize]; // Requires constructor arguments
Thanks.
You can't.
And if you truly want to conform to C++ standards, you should use std::vector.
FYI, it would probably be even more expensive than what you're trying to achieve. If you could do this, new would call a constructor. But since you'll modify the object later on anyway, the initial construction is useless.
1) std::vector
A std::vector really is the proper C++ way to do this.
std::vector<Bullet> bullets;
bullets.reserve(10); // allocate memory for bullets without constructing any
bullets.push_back(Bullet(10.2,"Bang")); // put a Bullet in the vector.
bullets.emplace_back(10.2,"Bang"); // (C++11 only) construct a Bullet in the vector without copying.
2) new [] operator
It is also possible to do this with new, but you really shouldn't. Manually managing resources with new/delete is an advanced task, similar to template meta-programming in that it's best left to library builders, who'll use these features to build efficient, high level libraries for you. In fact to do this correctly you'll basically be implementing the internals of std::vector.
When you use the new operator to allocate an array, every element in the array is default initialized. Your code could work if you added a default constructor to Bullet:
class Bullet {
public:
Bullet() {} // default constructor
Bullet(double,std::string const &) {}
};
std::unique_ptr<Bullet[]> b = new Bullet[10]; // default construct 10 bullets
Then, when you have the real data for a Bullet you can assign it to one of the elements of the array:
b[3] = Bullet(20.3,"Bang");
Note the use of unique_ptr to ensure that proper clean-up occurs, and that it's exception safe. Doing these things manually is difficult and error prone.
3) operator new
The new operator initializes its objects in addition to allocating space for them. If you want to simply allocate space, you can use operator new.
std::unique_ptr<Bullet,void(*)(Bullet*)> bullets(
static_cast<Bullet*>(::operator new(10 * sizeof(Bullet))),
[](Bullet *b){::operator delete(b);});
(Note that the unique_ptr ensures that the storage will be deallocated but no more. Specifically, if we construct any objects in this storage we have to manually destruct them and do so in an exception safe way.)
bullets now points to storage sufficient for an array of Bullets. You can construct an array in this storage:
new (bullets.get()) Bullet[10];
However the array construction again uses default initialization for each element, which we're trying to avoid.
AFAIK C++ doesn't specify any well defined method of constructing an array without constructing the elements. I imagine this is largely because doing so would be a no-op for most (all?) C++ implementations. So while the following is technically undefined, in practice it's pretty well defined.
bool constructed[10] = {}; // a place to mark which elements are constructed
// construct some elements of the array
for(int i=0;i<10;i+=2) {
try {
// pretend bullets points to the first element of a valid array. Otherwise 'bullets.get()+i' is undefined
new (bullets.get()+i) Bullet(10.2,"Bang");
constructed = true;
} catch(...) {}
}
That will construct elements of the array without using the default constructor. You don't have to construct every element, just the ones you want to use. However when destroying the elements you have to remember to destroy only the elements that were constructed.
// destruct the elements of the array that we constructed before
for(int i=0;i<10;++i) {
if(constructed[i]) {
bullets[i].~Bullet();
}
}
// unique_ptr destructor will take care of deallocating the storage
The above is a pretty simple case. Making non-trivial uses of this method exception safe without wrapping it all up in a class is more difficult. Wrapping it up in a class basically amounts to implementing std::vector.
4) std::vector
So just use std::vector.
It's possible to do what you want -- search for "operator new" if you really want to know how. But it's almost certainly a bad idea. Instead, use std::vector, which will take care of all the annoying details for you. You can use std::vector::reserve to allocate all the memory you'll use ahead of time.
Bullet** pBulletArray = new Bullet*[iBulletArraySize];
Then populate pBulletArray:
for(int i = 0; i < iBulletArraySize; i++)
{
pBulletArray[i] = new Bullet(arg0, arg1);
}
Just don't forget to free the memory using delete afterwards.
The way C++ new normally works is allocating the memory for the class instance and then calling the constructor for that instance. You basically have already allocated the memory for your instances.
You can call only the constructor for the first instance like this:
new((void*)pBulletArray) Bullet(int foo);
Calling the constructor of the second one would look like this (and so on)
new((void*)pBulletArray+1) Bullet(int bar);
if the Bullet constructor takes an int.
If what you're really after here is just fast allocation/deallocation, then you should look into "memory pools." I'd recommend using boost's implementation, rather than trying to roll your own. In particular, you would probably want to use an "object_pool".
I'm looking for a C++ container that's a cross between boost::array, boost::scoped_array and std::vector.
I want an array that's dynamically allocated via new[] (no custom allocators), contained in a type that has a meaningful copy-constructor.
boost::array is fixed-size, and although I don't need to resize anything, I don't know the size of the array at compile time.
boost::scoped_array doesn't have a copy constructor, and that means that I need to manually add one to each and every class using std::copy (my previous copy-paste intensive solution). This is also error prone, since you better make sure when you add a field that you added the correct initializer to the custom copy constructor; i.e. loads of boilerplate.
std::vector uses some pre-allocation system, and thus does not use operator new[]. This is problematic since it requires custom allocators, and worse, even that's not quite enough since there are some odd corner cases (which I don't fully understand) where return-by-value semantics are concerned that cause problems; I don't want the container to do anything fancy but simply contain a new[]'d array and copy it in it's copy constructor - and preferably overload all the usual suspects to be usable as a collection.
I don't need to resize anything, but the size must be controllable at runtime. Basically, a variant of scoped_array that happens to have a sane copy-constructor (for instance via std::copy) would be fine. Is there a standard collection for something like this?
Basically, I'm looking for a bog-standard dynamically allocated array with value semantics.
Inherit privately from std::vector, and then adjust appropriately. For example remove resize(), and perhaps add setsize() and a bool flag to determine if the size has been set.
Your copy constructor can invoke the std::vector copy constructor, and set the flag automatically to prevent further changes.
Doesn't sound hard to write. Something along the lines of this?
template <typename T> my_array {
T* m_ptr;
size_t m_size;
public:
my_array(size_t sz)
: m_ptr(new T[sz])
, m_size(sz)
{}
my_array(const my_array &other)
: m_ptr(new T[other.m_size])
, m_size(other.m_size)
{
std::copy(other.m_ptr, other.m_ptr + other.m_size, m_ptr);
}
~my_array() {
delete[] m_ptr;
}
// ... operator[], etc.
};
Usual disclaimers - this is off the top of my head, has not been compiled or anything.
To keep the long story short, I am unable to use the container from the STL and boost library and have to create my own.
My own generic container is coded in VC++6 and I need to know how to manually allocate memory for generic types before storing it in my own container. The generic types are all struct that can contain nested struct. All struct be it nested or not will contain only primitive types like char*, int, bool etc.
For example, when you call the insert function of std::vector, internally, std::vector will automatically perform a deep cloning of the generic type before storing it.
How can I duplicate this functionality (deep cloning of generic type) in my own container?
Please provide some sample code for performing deep cloning of generic type.
The std::vector (and most std containers) just call the type's copy constructor. This may or may not "deep clone" the object, depending on what the copy constructor does.
First and for all: if you want to clone any object, all it's aggregates should be cloned, too. This means that every struct/class involved in the cloning action should implement cloning behavior.
Then: the stl uses so called value-semantics: containers will always contain their elements 'by value'. Copying means creating copies of all container elements.
So in order to achieve cloning/deep copy behavior, the copy constructors of every member of the container's element type should implement deep copy behavior. Members of pointer-to-object type should also be deep-copied (not just copying the member pointer).
Note: code is untested, probably contains tons of exception-unsafety etc... and is merely used as a shallow :) example.
struct WithPointer {
int* pint;
WithPointer( int value = 0 ) : pint( new int ) { *pint = value; }
WithPointer( const WithPointer& other ) {
pint = new int;
*pint = *other.pint;
}
~WithPointer( ) { delete pint; } // important!
}
This class can be 'deep-copied' using an stl container:
std::vector<WithPointer> v;
WithPointer wp(1);
v.push_back( wp );
std::vector<WithPointer> v2 = v;
std::vector does not perform any "deep cloning" by itself. When you insert something into std::vector, the vector allocates raw memory for the new element in the appropriate space and then creates a new element in that memory area by using direct initialization (normally through placement-new) from the element you passed to the insertion method. In other words, in order to make a copy for a class type, std::vector calls the copy-constructor of the class type. If the element type is not a class type or a class type without appropriately defined copy-constructor, the deep copy will not take place.
This is what you should do in your container type, if you want to simulate copying functionality of std::vector.
I am trying to create a class which has a private member that is an array. I do not know the size of the array and will not until the value is passed into the constructor. What is the best way to go about defining the class constructor as well as the definition in the .h file to allow for this variable size of the array?
If you want a "real" C-style array, you have to add a pointer private member to your class, and allocate dynamically the memory for it in the constructor (with new). Obviously you must not forget to free it in the destructor.
class YourClass
{
private:
int * array;
size_t size;
// Private copy constructor operator to block copying of the object, see later
// C++03:
YourClass(const YourClass &); // no definition
// C++11:
YourClass(const YourClass&) = delete;
public:
YourClass(size_t Size) : array(new int[Size]), size(Size)
{
// do extra init stuff here
};
~YourClass()
{
delete [] array;
}
};
To make this work easier, you may consider to use a smart pointer (for example, a boost::scoped_array in C++03, or plain std::unique_ptr in C++11), that you may initialize using the initializer list before the constructor or simply in the constructor.
class YourClass
{
private:
boost::scoped_array<int> array; // or in C++11 std::unique_ptr<int[]> array;
size_t size;
public:
YourClass(size_t Size) : array(new int[Size]), size(Size)
{
// do extra init stuff here
}
// No need for a destructor, the scoped_array does the magic
};
Both these solutions produce noncopyable objects (you didn't specify if they had to be copyable and their copy semantic); if the class don't have to be copied (which happens most of times), these both are ok, and the compiler will generate an error if you try to copy/assign one class to another, in the first case because the default copy constructor has been overloaded with a private one (or plain deleted in C++11), in the second case because boost::scoped_array and std::unique_ptr are noncopyable.
If, instead, you want to have copyable objects, then you must decide if you want to create a copy that shares the array (so, just a pointer copy) or if you want to create a new, separate array for the other object.
In the first case, you must be very careful before freeing the allocated memory, since other objects may be using it; a reference-counter is the most common solution. You can be helped in this by boost::shared_array (or std::shared_ptr in C++11), which does all the tracking work automatically for you.
If instead you want to do a "deep copy", you'll have to allocate the new memory and copy all the objects of the source array to the target array. This is not completely trivial to do correctly, and is usually accomplished through the "copy and swap idiom".
Still, the simplest solution is to use a std::vector as a private member: it would handle all the allocation/deallocation stuff by itself, constructing/destroying itself correctly when the object of your class is constructed/destructed. Moreover, it implements the deep-copy semantic out of the box. If you need to make your callers access the vector read-only, then, you could write a getter that returns a const_iterator or a const reference to the vector object.
Using a std::vector is the best option.
If you ever need to pass it to a function that expects a pointer to an array (like the GSL often does), you can still pass &vec[0]...