I am trying to include a vector in my struct.
Here is my struct:
struct Region
{
bool hasPoly;
long size1;
long size2;
long size3;
long size4;
long size5;
long size6;
//Mesh* meshRef; // the mesh with the polygons for this region
long meshRef;
std::vector<int> PVS;
} typedef Region;
Is the vector in this declaration valid or would it make more sense to do a pointer to a vector. In the case of a pointer to a vector, do I need to allocate a new vector. How would I accomplish this?
Thanks!
Edit: The problem is that it ends up causing an error that points to xmemory.h, a file included with the MSVC++ platform.
void construct(pointer _Ptr, _Ty&& _Val)
{ // construct object at _Ptr with value _Val
::new ((void _FARQ *)_Ptr) _Ty(_STD forward<_Ty>(_Val)); // this is the line
}
Interestingly, it does not happen if I allocate it outside of the struct and simply in the function I use. Any ideas?
You can write it like this without the typedef:
struct Region
{
bool hasPoly;
long size1;
long size2;
long size3;
long size4;
long size5;
long size6;
long meshRef;
std::vector<int> PVS;
}; // no typedef required
To answer your questions:
Is the vector in this declaration valid
Yes, it is.
or would it make more sense to do a pointer to a vector.
No, probably not. If you did then you would have to implement copy constructor, assignment operator and destructor for the copy behavior. You would end up with the same but it would be extra work and potentially introduce bugs.
In the case of a pointer to a vector, do I need to allocate a new vector. How would I accomplish this?
You would need to implement the copy constructor, the copy assignment operator and the destructor:
// Copy constructor
Region(const Region & rhs) :
hasPoly(rhs.hasPoly),
// ... copy other members just like hasPoly above, except for PVS below:
PVS(new std::vector<int>(*rhs.PVS))
{
}
// Copy assignment operator
Region & operator=(const Region & rhs)
{
if (this != &rhs)
{
hasPoly = rhs.hasPoly;
// ... copy all fields like hasPoly above, except for PVS below:
delete PVS;
PVS = new std::vector<int>(*rhs.PVS);
}
return *this;
}
// Destructor
Region::~Region()
{
delete PVS;
}
Bottom line: your code is fine. You don't need to change it.
EDIT: Fix assignment operator: check for comparison against this and return *this.
It makes complete sense to do that and you don't need new in any respect, unless you actually want to alias a separate vector. In addition, you don't need any typedef stuff going on here.
It depends on how you use it.
If you want to copy the vector and data when copying the Region struct, then leave it as a non-pointer.
If you don't want it copied over, then you will want some sort of pointer to a vector.
If you use a pointer to a vector, you should be very careful about allocation/deallocation exception safety. If you can't scope your allocation in an exception safe way, then you'll leave a potential for memory leaks.
A couple options are:
Make sure that the code that allocates the vector (and uses the Region) also deallocates the vector, and is itself exception safe. This would require the Region to only exist inside that code's scope.
You could do this by simply allocating the vector on the stack, and pass that to the pointer in the Region. Then make sure you never return a Region object above that stack frame.
You could also use some sort of smart pointer -> vector in your Region.
The vector is fine. Be aware that if you copy this struct, then the vector will be copied with it. So in code with particular performance constraints, treat this struct the same way that you'd treat any other expensive-to-copy type.
In production code, some people would prefer you to use the class keyword rather than the struct keyword to define this class, since the vector member makes it non-POD. If you're the author of your own style guide there's nothing to worry about.
The typedef is wrong, though, just write struct Region { stuff };
Related
I was trying to work with arrays that are circular, and so ended up writing a CircularArray class for which I have attached the code. It uses a generic pointer for an array.
When I try creating a list of such circular arrays using std::vector, I face a problem when I try to use erase on it.
I don't see why this should be the case as I think the destructors and copy constructor work well enough normally.
Can someone please help with this?
Code:
CircularArray Class
template<class T> class CircularArray
{
//Class denoted by 'T' is expected to have a functional assignment operator, i.e. operator=(const T& ext) {} in place
protected:
int size=0;
int ori=0;
T* array;
private:
int pos=0;
public:
CircularArray() : CircularArray(0) {}
CircularArray(int s) {size=s;array=new T[s];}
CircularArray(T* ptr,int s)// : CircularArray(s)
{
size=s;array=new T[s];
for(int i=0;i<size;i++)
array[i]=ptr[i];
}
CircularArray(const CircularArray<T>& arr) : CircularArray(arr.size)
{
for(int i=0;i<size;i++)
array[i]=arr.array[i];
}
~CircularArray() {delete[] array;}
...
Testing Code
int main()
{
std::vector<CircularArray<int>> test;
int *a1=new int[3] {1,2,3},*a2=new int[3] {1,2,3},*a3=new int[3] {1,2,3};
CircularArray<int> n1(a1,3),n2(a2,3),n3(a3,3);
test.push_back(n1);
test.push_back(n2);
test.push_back(n3);
test.erase(test.begin()+1);
for(auto v : test)
{
for(int i=0;i<3;i++)
cout << v[i];
cout << "\n";
}
}
This program gives bad output after encountering the deleted part of the vector. Valgrind says that there is a memory corruption in trying to read freed memory.
What is wrong?
Vector elements must be copy/move assignable, yet you are relying on the default copy assignment operator which does not create any fresh memory. Your assigned objects all share the same memory space, later resulting in a double free.
Your constructors are good but you'll need a copy/move assignment operator too.
Read about the Rule of Five.
Also consider just using a std::vector for backing storage; it'll be much simpler.
Does delete[] work properly with generic arrays?
Yes.
Your (implicitly generated) copy and move assignment operator are wrong. They will copy the member pointer. Then you have two pointers to the same array, and one destructor deletes it once, and another deletes it for a second time, which leads to undefined behaviour.
When manually managing dynamic resource, it is essential to keep track of ownership, and make sure that it is released exactly once. A typical solution is to use a smart pointer. Your class has unique ownership (or it would have, if it didn't accidentally share the ownership in the assignment operators) of the dynamic array, so a unique pointer would be an appropriate choice.
On the other hand, you could use a vector container instead of a smart pointer.
As an academic exercise I created a custom vector implementation I'd like to support copying of non-pod types.
I would like the container to support storing elements that do not provide a default constructor.
When I reserve memory for the vector, and then push_back an element (which manages it's own resources and has a copy and assignment operator implemented - I'm ignoring move constructors for the moment) I have an issue using the copy-swap idiom for that type.
Because the swap happens on a type that is still uninitialised memory, after the swap, the destructor which is called for the temporary will attempt to free some piece of uninitialised data which of course blows up.
There are a few possible solutions I can see. One is ensure all non-pod types implement a default constructor and call that (placement new) on each element in the collection. I'm not a fan of this idea as it seems both wasteful and cumbersome.
Another is to memset the memory for the space of the type in the container to 0 before doing the swap (that way the temporary will be null and calling the destructor will operate without error). This feels kind of hacky to me though and I'm not sure if there is a better alternative (see the code below for an example of this) You could also memset all the reserved space to 0 after calling reserve for a bunch of elements but again this could be wasteful.
Is there documentation on how this is implemented for std::vector as calling reserve will not call the constructor for allocated elements, whereas resize will (and for types not implementing a default constructor a constructed temporary can be passed as a second parameter to the call)
Below is some code you can run to demonstrate the problem, I've omitted the actual vector code but the principle remains the same.
#include <iostream>
#include <cstring>
// Dumb example type - not something to ever use
class CustomType {
public:
CustomType(const char* info) {
size_t len = strlen(info) + 1;
info_ = new char[len];
for (int i = 0; i < len; ++i) {
info_[i] = info[i];
}
}
CustomType(const CustomType& customType) {
size_t len = strlen(customType.info_) + 1;
info_ = new char[len];
for (int i = 0; i < len; ++i) {
info_[i] = customType.info_[i];
}
}
CustomType& operator=(CustomType customType) {
swap(*this, customType);
return *this;
}
void swap(CustomType& lhs, CustomType& rhs) {
std::swap(lhs.info_, rhs.info_);
}
~CustomType() {
delete[] info_;
}
char* info_;
};
int main() {
CustomType customTypeToCopy("Test");
// Mimics one element in the array - uninitialised memory
char* mem = (char*)malloc(sizeof(CustomType));
// Cast to correct type (would be T for array element)
CustomType* customType = (CustomType*)mem;
// If memory is cleared, delete[] of null has no effect - all good
memset(mem, 0, sizeof(CustomType));
// If the above line is commented out, you get malloc error - pointer
// being freed, was not allocated
// Invokes assignment operator and copy/swap idiom
*customType = customTypeToCopy;
printf("%s\n", customType->info_);
printf("%s\n", customTypeToCopy.info_);
return 0;
}
Any information/advice would be greatly appreciated!
Solved!
Thank you to #Brian and #Nim for helping me understand the use case for when assignment (copy/swap) is valid.
To achieve what I wanted I simply needed to replace the line
*customType = customTypeToCopy;
with
new (customType) CustomType(customTypeToCopy);
Invoking the copy constructor not the assignment operator!
Thanks!
You don't use copy-and-swap for construction.
You use copy-and-swap for assignment in order to solve the following problem: the left side of the assignment is an already-initialized object, so it needs to free the resources it holds before having the right side's state copied or moved into it; but if the copy or move construction fails by throwing an exception, we want to keep the original state.
If you're doing construction rather than assignment---because the target is uninitialized---the problem solved by copy-and-swap doesn't exist. You just invoke the constructor with placement new. If it succeeds, great. If it fails by throwing an exception, the language guarantees that any subobjects already constructed are destroyed, and you just let the exception propagate upward; in the failure case the state of the target will be the same as it was before: uninitialized.
Since C++11, when using the move assignment operator, should I std::swap all my data, including POD types? I guess it doesn't make a difference for the example below, but I'd like to know what the generally accepted best practice is.
Example code:
class a
{
double* m_d;
unsigned int n;
public:
/// Another question: Should this be a const reference return?
const a& operator=(a&& other)
{
std::swap(m_d, other.m_d); /// correct
std::swap(n, other.n); /// correct ?
/// or
// n = other.n;
// other.n = 0;
}
}
You might like to consider a constructor of the form: - ie: there are always "meaningful" or defined values stores in n or m_d.
a() : m_d(nullptr), n(0)
{
}
I think this should be rewriten this way.
class a
{
public:
a& operator=(a&& other)
{
delete this->m_d; // avoid leaking
this->m_d = other.m_d;
other.m_d = nullptr;
this->n = other.n;
other.n = 0; // n may represents array size
return *this;
}
private:
double* m_d;
unsigned int n;
};
should I std::swap all my data
Not generally. Move semantics are there to make things faster, and swapping data that's stored directly in the objects will normally be slower than copying it, and possibly assigning some value to some of the moved-from data members.
For your specific scenario...
class a
{
double* m_d;
unsigned int n;
...it's not enough to consider just the data members to know what makes sense. For example, if you use your postulated combination of swap for non-POD members and assignment otherwise...
std::swap(m_d, other.m_d);
n = other.n;
other.n = 0;
...in the move constructor or assignment operator, then it might still leave your program state invalid if say the destructor skipped deleting m_d when n was 0, or if it checked n == 0 before overwriting m_d with a pointer to newly allocated memory, old memory may be leaked. You have to decide on the class invariants: the valid relationships of m_d and n, to make sure your move constructor and/or assignment operator leave the state valid for future operations. (Most often, the moved-from object's destructor may be the only thing left to run, but it's valid for a program to reuse the moved-from object - e.g. assigning it a new value and working on it in the next iteration of a loop....)
Separately, if your invariants allow a non-nullptr m_d while n == 0, then swapping m_ds is appealing as it gives the moved-from object ongoing control of any buffer the moved-to object may have had: that may save time allocating a buffer later; counter-balancing that pro, if the buffer's not needed later you've kept it allocated longer than necessary, and if it's not big enough you'll end up deleting and newing a larger buffer, but at least you're being lazy about it which tends to help performance (but profile if you have to care).
No, if efficiency is any concern, don't swap PODs. There is just no benefit compared to normal assignment, it just results in unnecessary copies. Also consider if setting the moved from POD to 0 is even required at all.
I wouldn't even swap the pointer. If this is an owning relationship, use unique_ptr and move from it, otherwise treat it just like a POD (copy it and set it to nullptr afterwards or whatever your program logic requires).
If you don't have to set your PODs to zero and you use smart pointers, you don't even have to implement your move operator at all.
Concerning the second part of your question:
As Mateusz already stated, the assignment operator should always return a normal (non-const) reference.
Suppose I have a class which manages a pointer to an internal buffer:
class Foo
{
public:
Foo();
...
private:
std::vector<unsigned char> m_buffer;
unsigned char* m_pointer;
};
Foo::Foo()
{
m_buffer.resize(100);
m_pointer = &m_buffer[0];
}
Now, suppose I also have correctly implemented rule-of-3 stuff including a copy constructor which copies the internal buffer, and then reassigns the pointer to the new copy of the internal buffer:
Foo::Foo(const Foo& f)
{
m_buffer = f.m_buffer;
m_pointer = &m_buffer[0];
}
If I also implement move semantics, is it safe to just copy the pointer and move the buffer?
Foo::Foo(Foo&& f) : m_buffer(std::move(f.m_buffer)), m_pointer(f.m_pointer)
{ }
In practice, I know this should work, because the std::vector move constructor is just moving the internal pointer - it's not actually reallocating anything so m_pointer still points to a valid address. However, I'm not sure if the standard guarantees this behavior. Does std::vector move semantics guarantee that no reallocation will occur, and thus all pointers/iterators to the vector are valid?
I'd do &m_buffer[0] again, simply so that you don't have to ask these questions. It's clearly not obviously intuitive, so don't do it. And, in doing so, you have nothing to lose whatsoever. Win-win.
Foo::Foo(Foo&& f)
: m_buffer(std::move(f.m_buffer))
, m_pointer(&m_buffer[0])
{}
I'm comfortable with it mostly because m_pointer is a view into the member m_buffer, rather than strictly a member in its own right.
Which does all sort of beg the question... why is it there? Can't you expose a member function to give you &m_buffer[0]?
I'll not comment the OP's code. All I'm doing is aswering this question:
Does std::vector move semantics guarantee that no reallocation will occur, and thus all pointers/iterators to the vector are valid?
Yes for the move constructor. It has constant complexity (as specified by 23.2.1/4, table 96 and note B) and for this reason the implementation has no choice other than stealing the memory from the original vector (so no memory reallocation occurs) and emptying the original vector.
No for the move assignment operator. The standard requires only linear complexity (as specified in the same paragraph and table mentioned above) because sometimes a reallocation is required. However, in some cirsunstances, it might have constant complexity (and no reallocation is performed) but it depends on the allocator. (You can read the excelent exposition on moved vectors by Howard Hinnant here.)
A better way to do this may be:
class Foo
{
std::vector<unsigned char> m_buffer;
size_t m_index;
unsigned char* get_pointer() { return &m_buffer[m_index];
};
ie rather than store a pointer to a vector element, store the index of it. That way it will be immune to copying/resizing of the vectors backing store.
The case of move construction is guaranteed to move the buffer from one container to the other, so from the point of view of the newly created object, the operation is fine.
On the other hand, you should be careful with this kind of code, as the donor object is left with a empty vector and a pointer referring to the vector in a different object. This means that after being moved from your object is in a fragile state that might cause issues if anyone accesses the interface and even more importantly if the destructor tries to use the pointer.
While in general there won't be any use of your object after being moved from (the assumption being that to be bound by an rvalue-reference it must be an rvalue), the fact is that you can move out of an lvalue by casting or by using std::move (which is basically a cast), in which case code might actually attempt to use your object.
so I have a structure like
struct GetResultStructure
{
int length;
char* ptr;
};
I need a way to make a full copy of it meaning I need a copy to have a structure with new ptr poinnting on to copy of data I had in original structure. Is It any how possible? I mean any structure I have which contains ptrs will have some fields with its lengths I need a function that would copy my structure coping all ptrs and data they point to by given array of lengthes... Any cool boost function for it? Or any way how to create such function?
For the specific scenario you describe, use a std::vector or some other sequence container. If you do so, then simply copying objects of type GetResultStructure will make copies of the pointed-to data as well:
struct GetResultStructure {
std::vector<char> data;
};
GetResultStructure a = GetData();
GetResultStructure b = a; // a and b have distinct, equivalent data vectors
In general, when you do need to implement this yourself, you do so by implementing a copy constructor and a copy assignment operator. The easiest way to do that is to use the copy-and-swap idiom, covered in great detail in What is the copy-and-swap idiom?
It's pretty much up to you to implement that. Normally you want to do it as a copy constructor so you only have to do it in one place. Unfortunately, there's no real magic to avoid telling the computer about how to copy your structure.
Of course, that only applies if your structure really is substantially different from something that's already written. The one you've given looks a lot like a string or (possibly) vector. Unless you really need to implement something new, you're probably better off just using one of those that's already provided.
Both a copy constructor and assignment operator should be implemented (in the way stated above). A technique which may aid in this process, however, is using a dereference operator (*) when copying pointer data. This will copy the pointer data rather than the memory locations. If you do ptr1 = ptr2 it simply sets the memory location of ptr1 to ptr2 which is why we dereference.
For instance, I'll just show a quick example for a copy constructor:
GetResultStructure(const GetResultStructure& other)
: length(other.length), ptr(new char[length]) // <--- VERY _important_ - initialization of pointer
{
// Alternatively, put your initialization here like so:
// ptr = new char[length];
for(int i=0;i<length;++i)
{
ptr[i] = new char;
*ptr[i] = *other.ptr[i]; // Copy the values - not the memory locations
}
}
And then obviously be sure to clean up in your destructor to prevent memory leaks.
Regards,
Dennis M.
GetResultStructure doCopy(GetResultStructure const& copy) {
GetResultStructure newstruct;
newstruct.length = copy.length;
newstruct.ptr = new char[newstruct.length];
memcpy(newstruct.ptr, copy.ptr, newstruct.length*sizeof(char));
return newstruct;
}
Should be simple. Yes, the sizeof(char) isn't really necessary, but there to show what to do for other data types.
Since you tagged it as C++: Write a copy constructor and an assignment operator,
within which you implement your deep copy code:
struct GetResultStructure
{
GetResultStructure(const GetResultStructure& other)
{
// Deep copy code in here
}
GetResultStructure& operator=(const GetResultStructure& other)
{
if (this != &other) {
// Deep copy code in here
}
return *this
}
int length;
char* ptr;
};