c++ mystic transfer of class array - c++

class Array
{
double *mx; int mn;
public:
Array();
~Array(){delete []mx};
Array& operator-(Array& b); //first right way
Array operator -(Array b); //wrong way, but I don't understand why
};
Array::Array ()
{
mn=10;
mx=new double[mn];
}
//first, works perfectly
Array& Array::operator -(Array& b)
{
int i=0;
for(i=0;i<mn ;i++)
this->mx[i]-=b.mx[i];
return *this;
}
// here is Error
Array Array::operator -(Array b)
{
int i=0;
for(i=0;i<mn ;i++)
this->mx[i]-=b.mx[i];
}
int main() {
Array x,b;
x=x-b;
}
If I use the first overload , all works right.
But if I use the second, all is compiled well, but when program is executed, i receive many errors like this:
"c++ ** glibc detected *** double free or corruption"
I can't figure out why this occurs.
As I understand, when I call Array Array::operator-(Array b), the object must be copied and all must be well, but there is error.
well i've read that i've to object that are allocated at the same place in the memory. but i've tried to do this:
Array Array::operator +(Array b)
{ Array c;
int i=0;
for(i=0;i<mn;i++)
this->mx[i]+=b.mx[i];
cout<<&this->mx<<" "<<&b.mx<<endl;
exit(0);
return c; }
i 've expected to receive same addresses in memory....
answer is 0xbfb45188 0xbfb45178 why are they equal?
furhermore, when i declare here name of class(A object)
compiler must give a new memory in stack for object
where am i wrong? i dont understand....

Array Array::operator -(Array b)
This line will create a copy of your array. As you don't have a copy constructor the compiler will just make a copy of all the fields including the pointer field "mx". Now you have two objects both pointing to the same allocated memory. When each one is destructed the delete [] will be called....
You need to either write a copy constructor or ensure that no copying takes place.
To do that pass by reference
Array Array::operator -(Array& b)
(That should probably be const too... but that's a different issue)

You violated the rule of three.

operator- should take a reference, otherwise you're performing needless copies. However, it doesn't need to. It certainly should return a value, because a - semantically gives you a new object. When you write c = a-b, you don't expect a or b to change.
As noted above, you don't need to take a reference into operator-, and in your second example you take by value. This is OK, except you have a second bug:
Your Array class has an internal buffer that it news on construction, and deletes when it gets destroyed (~Array).
However, it does not have a user-defined copy constructor, and the buffer is not automatically copied for you; only the pointer mx is copied.
So, when you copy the Array, you now have two objects with a pointer mx pointing to the same buffer. When one copy goes out of scope, that buffer is deleted; some time later, the other copy tries to do the same, and deleteing the same buffer twice is an error.
My suggestions:
Write a copy constructor and operator= into your class Array. Very important.
Have operator- take a reference anyway. It makes mores sense.
Hope that helps.

Related

Does delete[] work properly with generic arrays? If so why does using std::vector::erase on it cause error in freeing memory

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.

Is it possible to do a swap on return in c++, instead of return by value?

Suppose I'm coding a string class in C++ (I know I can use the library). The string length is variable and the storage space is dynamically allocated in the constructor and freed in the destructor. When the main function calls c=a+b (a,b,c are strings), the operator+ member function creates a temporary object that stores the concatenated string a+b, returns it to the main function, and then the operator= member function is called to free the string originally stored in c and copy data from the temporary string a+b to c, and finally the temporary a+b is destructed.
I'm wondering if there's a way to make this happen: instead of having the operator= copy data from a+b to c, I want it to swap the data pointers of a+b and c, so that when a+b is destructed, it destructs the original data in c (which is what we want), while c now takes the result of a+b without needing to copy.
I know coding a 2-parameter member function setToStrcat and calling c.setToStrcat(a,b) can do this. For example, the function can be coded as:
void String::setToStrcat(const String& a,const String& b){
String tmp(a.len+b.len); int i,j;
for(i=0;i<a.len;i++) tmp[i]=a[i];
for(j=0;j<b.len;i++,j++) tmp[i]=b[j];
tmp[i]='\0'; this->swap(tmp);
}
void String::swap(String& a){
int n=len; len=a.len; a.len=n;
char *s=str; str=a.str; a.str=s;
}
I omitted the definitions of my constructor (which allocates len+1 char-type spaces) and operator[] (which returns a reference of the ith character). The swap function swaps the data pointers and length variables between *this and tmp, so that when tmp is destructed after the swap, it is actually the data originally stored in *this (the String c in the main function) that is destructed. What *this now has in its possession (c.str) is the concatenated string a+b.
I would like to know if there is a way to optimize the performance of c=a+b to the same level. I tried c.swap(a+b) and changed the return type of a+b to String&, but I receive warning (reference to a local variable) and GDB shows that the temporary gets destructed before the swap happens, while I want the other way.
I think my question is general. In C++ programming, we often need a temporary object to store the result of a function, but when we assign it to another object in the main function, can we not copy the data but use a (much faster) swap of pointers instead? What is a neat way of making this happen?
In C++11, you can do this by writing a move constructor. Rvalue references were added to the language to solve this exact problem.
class String {
...
String(String&& s) : str(nullptr) {
this->swap(s);
}
String& operator=(String&& s) {
this->swap(s);
}
...
String operator+(String const& other) {
// (your implementation of concatenation here)
}
...
}
Then code like this will not trigger an extra copy constructor or a memory allocation, it will just move the allocated memory from the temporary (the thing returned from operator+) to the new object c.
String c = a + b;

C++ Move assignment operator: Do I want to be using std::swap with POD types?

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.

Adding vectors in C++

I'm a C++ beginner and I'm trying to write a method which will take two vectors and add together their contents.
For example,
v1{1,2,3}+v2{2,4,6} should yield v3{3,6,9}.
Here's what my code looks like right now:
Vec Vec::operator+(const Vec& original){
if(mySize != original.mySize){
throw invalid_argument ("No!");
}
Item* sumVector = new Item(mySize);
for(unsigned i=0; i<mySize; i++){
sumVector[i] = myArray[i] + original.myArray[i];
}
return * sumVector;
}
However, this isn't working because my assertion v3.getItem(0) == 3 is failing. I'm sure you already know this if you're answering this question but Vec is the name of one of my classes in this and Item is a typedef double.
As juanchopanza mentioned in the comments, sumVector is a pointer. Unfortunately for you, operator[] is defined for pointers, which may have given a confusing compile error for beginners.
For a solution that best retains the erroneous intent of the original code, this:
sumVector[i] = myArray[i] + original.myArray[i];
needs to be this:
(*sumVector)[i] = myArray[i] + original.myArray[i];
This way, you de-reference the pointer first, then access operator[] for the vector class. This is really bad though, and probably not even a solution.
You must understand what your code is doing. You are allocating a new array of Items on the heap, and then returning a copy of a Vec using the *Item, which is equivalent to Item[0], as the Vec's constructor. Not only are you constructor a Vec with a single double input (without seeing your class declarations I can't know if this is a valid thing, but it probably isn't), but this heap allocation of Items will never have a corresponding free since you have lost the only reference to it when you leave the function scope. You will never be able to free the memory, which means it is a memory leak.
The correct intent (I assume) is to create a local vector on the stack with computations, and then return it. This means changing two lines:
Item* sumVector = new Item(mySize)
return * sumVector;
to
Vec sumVector(mySize); //now this is actually a vector
return sumVector;
Note that vector types usually just hold a pointer in their class type, in addition to some metadata. This pointer value is allocated on the stack, and the pointer itself points to heap memory which the vector manages.
Change this statement
Item* sumVector = new Item(mySize);
to
Item* sumVector = new Item[mySize];
And instead of
return * sumVector;
there shall be
return sumVector;
provided that class Vec has a constructor with parameter of type Item *
However in any case there is a problem with the constructor because even it has a parameter of type Item * it does not know how many elements were allocated.
So you have to create an object of type Vec inside the body of the operator.
Also it would be better to declare the operator as
Vec Vec::operator+(const Vec& original) const;

C++ overloading the = operator

When overloading the = operator, should one make the contents of one object equal to the contents of the other object OR do you make the pointer of the object point to the same object?
Reading back on the question it seems that the contents should be copied and not the pointers. But I just can't figure it out, So I would be grateful if someone would explain what I should do, I know how to do both, I'm just not sure which one to choose.
class IntObject
{
private:
int *pi_One;
public:
IntObject(void);
IntObject::IntObject(int const &i_one);
~IntObject(void);
IntObject & operator=(const IntObject&);
};
IntObject::IntObject()
{
pi_One = new int(0);
}
IntObject::IntObject(int const &i_one)
{
pi_One = new int(i_one);
}
IntObject::~IntObject(void)
{
delete pi_One;
}
IntObject & IntObject::operator=(const IntObject& c) {
//This copies the pointer to the ints
this->pi_One = c.pi_One;
return *this;
}
It depends on what semantics you want to have in your type. If you want value semantics, then copy the contents (deep copy, as is the case in std::vector), if you want reference semantics (shallow copy, as in std::shared_ptr)
You should definitely copy the contents, not the pointers. Think about what you will do when one of the objects which both hold the same pointer is destroyed; you can't delete the pointer because the other object would be affected as well, but you can't not delete it either because you'd cause memory leaks. You'd have to use reference counting and everything would get a whole lot more complicated.
The contents should be copied (in fact, changing the pointer of the object shouldn't actually be possible - I can't imagine how you would do that - and even if it is somehow, you're not supposed to do it). You also have to take care of the differences between deep and shallow copies, especially if your class contains pointers (or containers with pointers in them).
Now that I think about it, I'm not even sure which pointer you could possibly want to reassign. Unless you are already working with a pointer - those already have an '=' operator that shouldn't be overloaded though.
The principle of least astonishment would say to copy the content. When using operator= on any other object, you wouldn't expect it to copy pointers.
If you keep your destructor as it is, then you should change assignment overload. It would be also wise that nobody is attempting assigning IntObject to itself:
IntObject & IntObject::operator=(const IntObject& c) {
if (this != &c)
{
//This copies the pointer to the ints
*this->pi_One = *c.pi_One;
}
return *this;
}
Otherwise, there will be attempt to free freed memory in IntObject's destructor