overloading operator = - c++

I have to create a function which overloads the = operator so that when you put object1 = object2; it'll copy over all the values inside object2 into object1.
My class looks like:
class foo {
private:
int max;
int *val;
size_t *listofVal;
}
And my overload function is declared as:
foo& foo::operator=(const foo& matrix);
foo::foo(std::istream& s); //constructor
how would I do this?

The best way to do this is by using Copy and Swap Idiom.
Also, note that if you feel the need of overloading the copy assignment operator then you also probably need to overload copy constructor as well as the destructor for your class.
Do have a look at Rule of Three.

Simply copying all the values is the default behaviour of the compiler supplied copy contructor. This is known as a "shallow-copy".
More elaborate behaviour is achieved by implementing your own constructor so that the objects (here values) pointed to by your reference are created anew in the copy.
foo::foo(std::istream& s) {
max = s.max;
val = new int;
*val = s->val;
listofVal = new size_t;
*listofVal = s->listofVal;
}
would be one way of achieving that which is known as a "deep copy".
But as one of your members is called listofVal I rather feel you are doing something other than storing a single value at the memory address it points, in which case you should be holing a counter to the number of elements contained therein, which I will henceforth assume to be the field you call max. To copy the whole list, your copy constructor would then need to be:
foo::foo(std::istream& s) {
max = s.max;
val = new int;
*val = s->val;
listofVal = new size_t[max];
for (int i = 0; i < max; ++i)
listofVal[i] = s->listofVal[i];
}
Ravi, yes, the copy constructor is a proof of construct and despite breaking the "Rule Of Three" can be implemented before the other two. Here is the assignment operator.
foo& foo::operator=(const foo& matrix) {
if (this != matrix) {
max = matrix.max;
val = new int;
*val = matrix->val;
listofVal = new size_t[max];
for (int i = 0; i < max; ++i)
listofVal[i] = matrix->listofVal[i];
}
}
would be suitabe for object1 = object2; assignment. I tend towards the copy constructor approach.
The methods need to be members to access the private data so your class should be like
class foo {
///...///As before
foo &operator=(const foo& matrix);
};
Of course it needs a destructor but as it was not explicitly requested I didn't want to answer what wasn't asked.
Following on from the link to the Copy and Swap idiom, when the LHS may already contain data, for robust assignment you might consider:
foo& foo::operator=(const foo& matrix) {
if (this != matrix) {
val = new int;
*val = matrix->val;
size_t* newArray = new size_t[max];
int newMax = matrix.max;
std::copy(matrix.listofVal, matrix.listofVal + max, newArray);
if (listofVal) delete listofVal;
listofVal = newArray;
max = newMax;
}
}
I would add that assigning local objects on the heap can cause memory leaks (if the method breaks before they are assigned to an object responsible for their deletion), but that is just a whole nother layer of parannoia when we have enough to do preserving class integrity.

Googling for "C++ Assignment Operator" gives you this useful site ;-)

Related

C++ Copy constructor for a pointer to vector of pointers

I have a class A, which has as a member a pointer to a vector of pointers (current), the vector which contains a pair of an integer and an object of class B . I need to be able to create copies for objects of class A, and for that I use a Clone function (see code below). However, when I use this function, the pointers seem to be pointing to the same memory location, instead of different ones. I think the solution to this is to implement a copy constructor for my class in order to be able to properly copy my objects, but I am failing to do so.
Here is how my class looks like and the several tries I had for implementing the copy constructor:
class A {
public:
A();
A(const A &a);
~A();
A* Clone() {return new A(*this);}
std::vector<std::pair<unsigned int, B*>> *current;
};
EDIT: The constructor and destructor are implemented as follows:
A::A() {
current = new vector<std::pair<unsigned int, B*>>;
}
A::~A() {
std::vector<std::pair<unsigned int, B*>>::iterator cit = current->begin(), cend = current->end();
for (; cit != cend; ++cit) {
delete cit->second;
}
delete current;
}
Option #1:
A::A(const A &a){
*current = *a.current;
}
Option #2:
A::A(const A &a){
for(int i = 0; i < current->size(); i++) {
(*current)[i] = (*a.current)[i];
}
}
Option #3:
A::A(const A &a){
for(int i = 0; i < current->size(); i++) {
(*current)[i].first = (*a.current)[i].first;
(*current)[i].second = new B((*a.current)[i].second);
}
}
Options #1 and #2 give me segmentation fault, while for #3 I get the error: no match for operator *
Which is the correct way to implement the copy constructor and also should my Clone function be implemented differently?
Your constructor does not initialise the current member at all. In any of the options.
From there, accessing its value (i.e. the value of the pointer named current) gives undefined behaviour. And so does dereferencing it. The usages of *current or *a.current in all options (and variations therefore) therefore ALL give undefined behaviour.
If you insist that the member current must be a pointer, it must be initialised in ALL constructors. For example, the constructor A::A() (which you haven't shown) must look something like
A::A() : current(new std::vector<std::pair<unsigned int, B*>>(0))
{
// initialised current with no elements
// add pairs to the vector
current->push_back(std::make_pair(0U, new B));
current->push_back(std::make_pair(42U, new B));
}
and the copy constructor must start with something akin to
A::A(const A &a) : current (new std::vector<std::pair<unsigned int, B *>>(a.current->size())
{
for(int i = 0; i < current->size(); i++)
{
(*current)[i].first = (*(a.current))[i].first;
(*current)[i].second = new B((*(a.current))[i].second);
}
}
More generally, however, there is actually no reason for current to be a pointer created using operator new. In that case the constructors could be simplified to
A::A() : current(0)
{
// add pairs to the vector
current.push_back(std::make_pair(0U, new B));
current.push_back(std::make_pair(42U, new B));
}
and the copy constructor to
A::A(const A &a) : current (a.current.size())
{
for(int i = 0; i < current.size(); i++)
{
current[i].first = a.current[i].first;
current[i].second = new B(a.current[i].second);
}
}
You've also provided no compelling information to suggest that current needs to be vector<pair<unsigned, B *>> rather than vector<pair<unsigned, B>>. If the vector doesn't need to hold pointers (i.e. it holds objects directly) then, practically, you will not need to define the copy constructor at all - the compiler-generated default will suffice. And your code will not need to use operator new at all (except, possibly, in A::Clone()).
Note that, if you do actually need to hand-roll a copy constructor, you will probably need to also hand-roll an operator=() and a destructor. Look up "rule of three" (before C++11) or (C++11 and later) "rule of five" and "rule of zero" for more information.

Why do we need to delete pointers inside copy assignment operator

I have seen several examples of copy assignment operator and could not understand why do we need to delete pointers inside copy assignment operator. For example if I have the following class
class MyClass
{
public:
MyClass(int a)
{
x = new int(a);
}
MyClass& operator=(const MyClass& pMyClass)
{
*x = *(pMyClass.x);
// ?????????
// delete x;
// x = new int(*(pMyClass.x));
}
~MyClass()
{
delete x;
}
private:
int* x;
}
What is wrong with *x = *(pMyClass.x) line? I am just copying object pointed by pMyClass.x why I need to delete and create it again?. Could anyone please give example when this code will cause memory leak?
So this is an example [extracted from Bjarne Stroustrup's "A tour of C++ (2nd edition)] of a copy assignment of a user defined vector class:
Vector& Vector::operator=(const Vector& a) // copy assignment
{
double∗ p = new double[a.sz];
for (int i=0; i!=a.sz; ++i)
p[i] = a.elem[i];
delete[] elem; // delete old elements
elem = p; // here elem is the vector's data holding member array
sz = a.sz;
return ∗this;
}
To understand why at line 6 we have the deletion operation:
delete[] elem; // delete old elements
we first need to first understand the distinction between copy constructor and copy assignment. In the first case (copy constructor) we create a completely new object, whereas in the second case (copy assignment, the one we're actually interested in) we already have an existing object into which we just want to copy the contents of another given object of the same type.
Given the fact that we already have an existing object, we first need to clear it's contents so that we are then able to copy the desired content from the object we intent to copy.
I hope that answers your question.
It is a valid code. But if instead of the pointer to a single object you will have a pointer to first element of an array and arrays may have different sizes then you need to delete the array that to reallocate it with the new size.
Nothing wrong with *x = *(pMyClass.x) when you copying value from one class instance to other. I think, in general, deleting an object (if it is not just int) can prevent usage of new object with new data if before operator= execution address stored in x was sent to some other part of program.

Assign class constructor to a new constructor with parameter in C++

I create a class type Test and constructor with parameter, however, when I want to assign the constructor I create to a new constructor through the function f, the program crashes! Did anybody know why!?
The code:
class Test
{
public:
int number;
int *a;
Test(int n){
a = new int[n];
}
~Test(){
delete []a;
}
};
Test f(Test Ft1)
{
// Do something.
return Ft1;
}
int main()
{
Test t1(3);
t1.number = 5;
Test t2 = f(t1);
return 0;
}
The problem is that you are deleting twice the same array a when t1 and t2 destructors are called:
t1 and t2 have their member variable a pointing to the same memory location. When you do Test t2 = f(t1), a copy of t1 is created and is assigned to t2. You did not define a specific copy constructor, so the compiler defined it implicitly for you. However it simply copies the value of a (and does not do a new allocation as you might expect).
As best practice, I would recommend to add your own:
- copy constructor
- copy assignment
(cf rule of three)
Concerning the variable member a design:
- If you want t1 and t2 to point to the same array, then you can use shared_ptr
- If you want t1 and t2 to have their own array, then it would be simpler to use a vector<int> for a
Edit: in case you need to use a raw pointer, here is a quick example of how you can manage the memory in copy constructor and operator assignment. May I recommend you to read a reference book about it (for instance Effective C++ , chapter 11)? It will explain you the key concepts and the pitfalls.
class Test{
public:
int number;
int *a;
Test(int n){
a = new int[n];
}
~Test(){
delete [] a;
}
Test(const Test& that)
{
int size = sizeof(that.a);
a = new int[size];
memcpy (a, that.a, sizeof(size));
}
Test& operator=(const Test& that)
{
if (this != &that)
{
delete [] a;
int size = sizeof(that.a);
a = new int[size];
memcpy (a, that.a, sizeof(size));
}
return *this;
}
};
Test f(Test Ft1){
//do something
return Ft1;
}
int main(){
Test t1(3);
t1.number = 5;
Test t2 = f(t1);
// Test t3(t1); // calls copy constructor
// t3 = t1; // calls assignment operator
return 0;
}
The cause of your problem is that there is a thing called "binary copy". When special assignment/copy constructors are not defined, this binary copy kicks in. When one of your object gets copied over another, 2 different instances start own the same array because the pointer gets overwritten and the original array from the destination object gets leaked.
Compiler thinks that it is ok to copy contents of one object to another with a simple memcpy() (the picture is slightly more simplified but in essence what I write is correct). This is a constant source of problems, but this is how the language is defined. There is no way to do it any other way today. Tons of code are written and these tons expect exactly this.
First you need to decide what should happen with this array after copying. Should both objects co-own the array of the source object, should this array be duplicated at this point or anything else. Once you decide this, you need to implement this strategy in the assignment/copy constructors.

Deallocating memory from a private class variable

#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class myClass{
public:
int *num1;
myClass();
};
myClass::myClass(){
num1 = new int[1];
num1[0] = 10;
}
int main()
{
myClass *myclass;
myclass = new myClass[10];
cout << myclass[0].num1[0] << endl;
delete &myclass[0];
cout << myclass[0].num1[0] << endl;
}
I want to delete the first instance of myclass (myclass[0]).
This code does not run correctly, it fails during the delete part. There is probably something I am missing.
What did I do wrong?
You cannot delete just a portion of an array created with new. new allocates a block of memory which can only be deleteed all together.
If you want an object to free its own internal data you'll have to arrange for the class, which should encapsulate and hide its own internal resources, to do that itself.
If you want a smaller block of memory holding the array you allocated, then you must allocate a smaller block and move the contents that you wish to keep into the new block, and then delete the entire old block:
int *arr = new int[10];
int *tmp = new int[9];
std::copy(arr+1, arr+10, tmp);
delete [] arr;
arr = tmp;
You need to design your class to manage its own resources, and to handle copying or moving. Your current myClass allocates an array but relies on other code to handle cleaning up. This is not a good way to go about doing this, because often no other code is in a good position to do the correct thing, and even when you could you'll very frequently make mistakes.
Since you're allocating in the constructor you need a destructor that handles deallocation. And then since you implement one of three special operations (copy-ctor, copy-assignment, destructor) you need to consider implementing them all. (This is called 'The Rule of Three'. In C++11 it becomes 'The Rule of Five' with the addition of move-ctors and move assignment.)
class myClass {
public:
myClass();
// destructor to handle destroying internal resources correctly
~myClass();
// copy constructor and copy assignment operator, to handle copying correctly
myClass(myClass const &rhs);
myClass &operator=(myClass const &rhs);
// move constructor and move assignment operator, to handle moves correctly (C++11)
myClass(myClass && rhs);
myClass &operator= (myClass &&rhs);
private:
int *num1; // private so external code can't screw it up
public:
// limited access to num1
int size() const { if (num1) return 1; else return 0; }
int &operator[] (size_t i) { return num1[i]; }
};
You can implement the constructor just as you did, or you could use the initializer list and C++11 uniform initialization:
myClass::myClass() : num1(new int[1]{10}) {}
Now, the destructor you want depends on the semantics you want the class to have, and the particular invariants you want to maintain. 'value' semantics are the norm in C++ (if you're familiar with Java or C# those languages encourage or require 'reference' semantics for user defined types). Here's a destructor you might use if you want value semantics, and if you maintain an invariant that num1 always owns memory or is null.
myClass::~myClass() { delete num1; }
Copying and moving can be handled in different ways. If you want to disallow them entirely you can say (in C++11):
myClass::myClass(myClass const &rhs) = delete;
myClass &myClass::operator=(myClass const &rhs) = delete;
myClass::myClass(myClass && rhs) = delete;
myClass &myClass::operator= (myClass &&rhs) = delete;
Or if you want to allow copying and or moving (and maintain value semantics and the invariant mentioned above) then you can implement either or both of these pairs of functions:
myClass::myClass(myClass const &rhs) : num1( rhs.size() ? new int[1]{rhs[0]} : nullptr) {}
myClass &myClass::operator=(myClass const &rhs) {
if (num1)
num1[0] = rhs[0];
}
myClass::myClass(myClass && rhs) : num1(rhs.num1) { rhs.num1 = nullptr; } // remember to maintain the invariant that num1 owns the thing it points at, and since raw pointers don't handle shared ownership only one thing can own the int, and therefore only one myClass may point at it. rhs.num1 must be made to point at something else...
myClass &myClass::operator= (myClass &&rhs) { std::swap(num1, rhs.num1); } // steal rhs.num1 and leave it to rhs to destroy our own num1 if necessary. We could also destroy it ourselves if we wanted to.
With this implementation you can now treat a myClass object the same as you would an int or any other 'value' type. You no longer need to worry about managing its internal resources; it will take care of them itself.
int main() {
std::vector<myClass> myclassvec(10);
cout << myclassvec[0][0] << '\n';
myclassvec.erase(myclassvec.begin()); // erase the first element
cout << myclassvec[0][0] << '\n'; // access the new first element (previously the second element);
}
Create a function inside of your class the handles the deletion of its private members, maybe called FreeMem(int index)
void myClass::FreeMem()
{
delete [] num1
}
But honestly, freeing memory of an object without the use of a destructor in this sort of a program is hazardous and downright bad practice. I would recommend freeing the memory in your destructor, so when the object terminates it frees the memory,
myClass::~myClass()
{
delete [] num1;
}
Another thing to note on, if you're only creating one value in your dynamic variable, it would be easier to write it as:
int * pnum = new int;
//or in your class..
pnum = new int;
among other things, you have a lot of flaws in your program. I would recommend re-reading up on classes again.

Will this addition class cause a memory leak?

Here is an example of a class that is made available for the + operation.
class A
{
public:
int *array;
A()
{
array = new int[10];
}
~A()
{
delete[] array;
}
A operator+ (const A &b)
{
A c;
for(int i=0; i<10; i++)
c.array[i] += array[i] + b.array[i];
return c;
}
};
int main()
{
A a,b,c,d;
/* puts some random numbers into the arrays of b,c and d */
a = b+c+d;
}
Will a run the destructor before copying the result of b+c+d or not? If not, how do I make sure no memory is leaked?
The + operator overload is designed this way such that no operand is modified.
You need to add an equals operator to A. Also, you will likely want to create a copy constructor.
When a becomes the return from b+c+d, the array pointer in a gets over written without delete[] ever being called on it. You need to make an operator= that deletes the array.
An example of an operator= is below:
A& operator=(A const& a)
{
if (&a != this) {
int* tmp = this->array;
this->array = new int[10];
//copy a.array to this->array
delete[] tmp;
}
return *this;
}
There's a lot of subtleties in this if you're new to operator=.
In particular, the check whether or not a is equal to this is necessary because it's perfectly valid to write:
A a;
a = a;
This would cause a pointless copy, and in most cases of operator= will cause bugs.
The other subtlety is less of a requirement than that one and more of a coding style (though a very wide spread standard). When copying something that is dynamically allocated, you always want to allocate and copy before you release. That way, if new throws an exception (or something else fails), the object is still in a stable state, though with it's old data instead of the new expected dated.
Will this cause memory leak?
Yes, it will. You forgot to add copy constructor and assignment operator. See Rule of Three
You could also use std::vector<int> for A::array instead of int*. In this case you wouldn't need to worry about copy constructor/assignment operator (as long as you don't add something else that must be handled in destrcutor).