attempting to reference a deleted function - ostream - c++

I am trying to add to my class the output operator << but in compiling (VS2013) I have a message:
"error C2280:
'std::basic_ostream<char,std::char_traits<char>>::basic_ostream(const
std::basic_ostream<char,std::char_traits<char>> &)' : attempting to
reference a deleted function".
here is my code:
#include "Client.h"
Client::Client(MyString id, MyString full_name, char gender, unsigned short age, unsigned short hobbies_num, char** hobbies_list)
{
this->id = id;
this->full_name = full_name;
if (gender == 'm' || gender == 'M')
this->gender = 'M';
else if (gender == 'f' || gender == 'F')
this->gender = 'F';
else
cout << "wrong gender value" << endl;
if (age >= 18)
this->age = age;
else
cout << "wrong age value" << endl;
this->hobbies_num = hobbies_num;
this->hobbies_list = hobbies_list;
}
Client::Client(const Client& other)
{
this->id = other.id;
this->full_name = other.full_name;
this->gender = other.gender;
this->age = other.age;
this->hobbies_num = other.hobbies_num;
this->hobbies_list = other.hobbies_list;
}
Client::~Client()
{
for (int i = 0; i < hobbies_num; i++) // deleting 2 dimension array
delete[] hobbies_list[i];
delete[] hobbies_list;
}
Client& Client::operator = (const Client& other)
{
if (this->id == other.id) //checks if the client is not the same client
return *this;
else
{
for (int i = 0; i < hobbies_num; i++) // deleting 2 dimension array
delete[] hobbies_list[i];
delete[] hobbies_list;
return Client(other);
}
}
ostream& operator << (ostream& cout, const Client& for_print)
{
return cout << for_print.id << endl
<< for_print.full_name << endl
<< for_print.gender << endl
<< for_print.age << endl
<< for_print.hobbies_num << endl;
}
The message is on the line stating at return cout.
here are the prototypes:
#include "MyString.h"
#include <iostream>
#include <stdlib.h>
using namespace std;
class Client
{
MyString id;
MyString full_name;
char gender;
unsigned short age;
unsigned short hobbies_num;
char ** hobbies_list;
public:
Client(MyString, MyString, char, unsigned short, unsigned short, char**);
Client(const Client& other);
~Client(); //dtor
Client& operator = (const Client&); //=
friend ostream& operator << (ostream&, const Client& for_print);
};
I didn't find any solution online. The same command works for me in another class at the same solution.

You don't post the exact place of the compiler error, but I'll try to guess it. Suppose you try to do the following in your code (I won't try to use any C++11 construct to be portable):
char *hobbies[] = {
"hobbie1",
"hobbie2",
/* ... */
};
...
Client a("cl1", "joseph", 'm', 20, hobbies, sizeof hobbies/sizeof hobbies[0]);
/* object declaration with initialization, constructor is called for a */
and then
a = Client("cl2", "john", 'm', 22, hobbies, sizeof hobbies/sizeof hobbies[0]);
/* assignment statemement, constructor is being called for right expression
* and then assignment operator is called to assign it to a.
* Equivalent to:
* a.Client::operator=(Client("cl2",...));
* a new object is created by the compiler, passed as parameter and destroyed
* when the call to operator= is finished, before assigning to a.
*/
In this last statement, the compiler tries to construct a new object (for the expression evaluation) and assign it to a, using operator Client::operator=(const Client&other); with parameter other instantiated to this new created object (the compiler just deallocates it, calling the destructor, when the statement finishes, you can check this putting tracing code in the ~Client() body). Just when you return the value Client(other) (in the final return statement of the Client::operator= body), you instantiate a new expression of type Client with values copied with something that will be deleted by the compiler when the expression evaluation finishes (either the client created to pass it to the assignment operator or the one you construct for the return statement) They cease to exist when the return statement is just executed, so you cannot access them outside the operator call (I think this is the error you get from the compiler). You had better to rewrite the Client::operator=(const Client& other) this way:
Client& Client::operator=(const Client& other)
{
if (this == &other) /* the same object in both sides */
return *this;
else {
/* delete local memory assignated
* **in constructor** to object, not elsewhere
*/
/* do the actual assignments onto *this,
* don't create another instance or value. This
* is an assignment operation, you are supposed to
* change the values of *this
*/
return *this;
/* **never** return a local copy made by the compiler
* inside the function call, it ceases to exist just
* on returning from it */
} /* if */
} /* Client::operator=(const Client&) */
I don't believe this same example compiles ok in another environment, it's wrong C++ construct.
You can also see how I have called the constructor with static char arrays (not strings) so they must not be deallocated in the destructor of Client (to illustrate that you might better not deallocate memory in the destructor if it has been allocated elsewhere).

Related

Why the result of this program is 3 "born"?And 4 dead

This is main.cpp:
int main() {
Person arr[2] = {
Person(18,180),
Person(20,173)
};
arr[0]+arr[1];
return 0;
}
This is Person.h:
class Person
{
private:
int age;
int height;
public:
Person(int age=20,int height=180);
~Person();
void operator+(Person);
};
And this is Person.cpp:
Person::Person(int age,int height) {
(*this).age = age;
(*this).height = height;
cout << "I'm born.\n";
}
Person::~Person() {
cout << "I'm dead.\n";
}
void Person::operator+(Person a) {
Person result;
result.age = (*this).age + a.age;
result.height = (*this).height + a.height;
cout << result.age << endl;
cout << result.height << endl;
}
Why the result of this program is 3 "born"?And 4 dead?
What are the procedures of initializing the array of objects 'arr'?
In the operator+ the second argument of the addition, which is the first parameter, is passed by value, and so is called the copy constructor (which is not redefined and so you are not taking track of the object build with it) in order to build it, and so at the end of the function call that object is destructed (and so this is your 4th "hidden" dead person)
The missing born person is a clone! Note operator+ take an argument by value, so the copy constructor is called (the default one in this case). To see this add
Person::Person(const Person &p) {
this->age = p.age;
this->height = p.height;
cout << "I'm a clone.\n";
}
to your code - then it is clear why there are 4 people dead in the end. A better idea is you have your odd operator to have this signature to avoid copies and be explicit:
void Person::operator+(const Person &a) const;
Also, no point in using *this when you have the arrow operator.
Let;s count together the number of constructor and destructor calls.
In thsi declaration of an array
Person arr[2] = {
Person(18,180),
Person(20,173)
};
the constructor is called two times because two objects of the class are being created. Here is taken place the elision of calls of the copy constructor.
In this call
arr[0]+arr[1];
there is used the following function
void Person::operator+(Person a) {
Person result;
result.age = (*this).age + a.age;
result.height = (*this).height + a.height;
cout << result.age << endl;
cout << result.height << endl;
}
The argument arr[1] is passed to the function by value calling the implicitly defined copy constructor. So a third object of the class is created.
Within the function there is created a fourth object in this declaration
Person result;
So four objects were created three of them using the constructor with parameters and one with the copy constructor. So as a result four destructors were also called.
The operator should be declared and defined at least like
Person Person::operator +( const Person &a) const {
return Person( age + a.age, height + a.height );
}
On the other hand it is better to make the constructor explicit. For example
explicit Person(int age=20,int height=180) : age( age ), height( height )
{
}

C++ program crashing (has something to do with with dynamic memory)

I'm having the weird crashing that occurs everytime it goes to the for loop to initialize each position to undefined. Can anyone shine light on why this is happening?
#include
#include
#include
using namespace std;
class MyPhoneBook
{
public:
MyPhoneBook(int, string, string, string, string);
MyPhoneBook();
~MyPhoneBook();
void initialise(int, int, string, string, string, string);
bool search(string&, int);
bool find_free_pos();
void add();
void remove();
void display(int);
friend istream& operator >> (istream& in, MyPhoneBook& ph);
friend ostream& operator << (ostream& out, MyPhoneBook& ph);
private:
int *recordid;
int *status; // -1 is no longer at this number, 0 is blocked, 1 is not blocked, 2 is free
string *name, *areacode, *number, *group;
};
int main(int argc, char** argv)
{
cout << "test 1" << endl;
MyPhoneBook *myphbk; // pointer that will point to an object of a MyPhoneBook class
myphbk = new MyPhoneBook[100]; // now its using dynamic memory
cout << "test 2" << endl; //just for testing
int pos = 0;
for(pos = 0; pos < 100; pos++) // initializing everything to undefined, and position to free (position is the second parameter sended in)
{
myphbk[pos].initialise( (pos+1) , 2 , "Undefined" , "Undefined" , "Undefined" , "Undefined");
}
cout << "test 3" << endl; //just for testing
}
return 0;
void MyPhoneBook::initialise(int recordid_,int status_, string name_, string areacode_, string number_, string group_)
{
//now assign them to private member variables
*recordid = recordid_;
*status = status_;
*name = name_;
*areacode = areacode_;
*number = number_;
*group = group_;
//end of assigning
}
does anyone have any idea why can't my program reach the cout << "test 3" << endl part of the program without crashing?
Since you did not paste the constructor of MyPhoneBook i can only guess, but the problem could be the lines
*recordid = recordid_;
*status = status_;
if you did not assign a valid address to recordid and status in the constructor, e.g. by
recordid = new int;
status = new int;
You might want to declare those member variables as a simple int.

Even the Copy Assignment Operator can't assist

Kindly help me figure out where the issue is. I have followed the rule of three as well and made several modifications to the code.
#include <iostream>
using namespace std;
class AStack {
public:
AStack();
AStack(int);
AStack(const AStack&);
~AStack();
AStack& operator = (const AStack& s);
void push(int);
int pop();
int top();
bool isEmpty();
void flush();
private:
int capacity ;
int* a;
int index = -1; // Index of the top most element
};
AStack::AStack() {
a = new int[25];
capacity = 25;
}
AStack::AStack(int size) {
a = new int[size];
capacity = size;
}
AStack::AStack(const AStack& s) {
capacity = s.capacity;
delete[] a; // To avoid memory leak
a = new int[capacity];
for (int i = 0; i < capacity; i++) {
a[i] = s.a[i];
}
index = s.index;
}
AStack::~AStack() {
delete[] a;
}
AStack& AStack::operator = (const AStack& s) {
capacity = s.capacity;
delete[] a; // To avoid memory leak
int* a = new int[capacity];
for (int i = 0; i < capacity; i++) {
a[i] = s.a[i];
}
index = s.index;
return *this;
}
void AStack::push(int x) {
if (index == capacity - 1) {
cout << "\n\nThe stack is full. Couldn't insert " << x << "\n\n";
return;
}
a[++index] = x;
}
int AStack::pop() {
if (index == -1) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
return a[index--];
}
int AStack::top() {
if (index == -1) {
cout << "\n\nNo elements in the Stack\n\n";
return -1;
}
return a[index];
}
bool AStack::isEmpty() {
return (index == -1);
}
void AStack::flush() {
if (index == -1) {
cout << "\n\nNo elements in the Stack to flush\n\n";
return;
}
cout << "\n\nFlushing the Stack: ";
while (index != -1) {
cout << a[index--] << " ";
}
cout << endl << endl;
}
AStack& reverseStack(AStack& s1) {
AStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
return s1;
}
int main() {
AStack s1;
s1.push(1);
s1.push(2);
s1.push(3);
s1.push(4);
s1.push(5);
s1 = reverseStack(s1);
cout << "\n\nFlushing s1:\n";
s1.flush();
system("pause");
return 0;
}
I fail to understand how even after defining the appropriate copy assignment operator, the values in s1 after returning from the function are garbage values.
If your copy constructor is correct, and your destructor is correct, your assignment operator could be written in a much easier and safer fashion.
Currently, your assignment operator has two major flaws:
No check for self-assignment.
Changing the state of this before you know you can successfully allocate the
memory (your code is not exception safe).
The reason for your error is that the call to reverseStack returns a reference to the current object. This invoked the assignment operator, thus your assignment operator was assigning the current object to the current object. Thus issue 1 above gets triggered.
You delete yourself, and then you reallocate yourself, but where did you get the values from in the loop to assign? They were deleted, thus they're garbage.
For item 2 above, these lines change this before you allocate memory:
capacity = s.capacity;
delete[] a; // To avoid memory leak
What happens if the call to new[] throws an exception? You've messed up your object by not only changing the capacity value, but you've also destroyed your data in the object by calling delete[] prematurely.
The other issue (which needs to be fixed to use the copy/swap idiom later in the answer), is that your copy constructor is deallocating memory it never allocated:
AStack::AStack(const AStack& s) {
capacity = s.capacity;
delete[] a; // ?? What
Remove the line with the delete[] a, since you are more than likely calling delete[] on a pointer that's pointing to garbage.
Now, to rid you of these issues with the assignment operator, the copy/swap idiom should be used. This requires a working copy constructor and a working destructor before you can utilize this method. That's why we needed to fix your copy constructor first before proceeding.
#include <algorithm>
//...
AStack& AStack::operator = (AStack s)
{
std::swap(capacity, s.capacity);
std::swap(a, s.a);
std::swap(index, s.index);
return *this;
}
Note that we do not need to check for self assignment, as the object that is passed by value is a brand new, temporary object that we are taking the values from, and never the current object's values (again, this is the reason for your original code to fail).
Also, if new[] threw an exception, it would have been thrown on the call to the assignment operator when creating the temporary object that is passed by value. Thus we never get the chance to inadvertently mess up our object because of new[] throwing an exception.
Please read up on what the copy/swap idiom is, and why this is the easiest, safest, and robust way to write an assignment operator. This answer explains in detail what you need to know:
What is the copy-and-swap idiom?
Here is a live example of the fixed code. Note that there are other changes, such as removing the default constructor and making the Attack(int) destructor take a default parameter of 25.
Live Example: http://ideone.com/KbA20D

Access violation writing location when using pointers

I'm trying to write a program that allows a user to input data into a text file to organize class assignments. The user can display the list of assignments, enter an assignment into the file, and search for specific course work that is due. I am having a problem where I get an access violation writing location error and I'm not entirely sure how to fix it. I have looked at previous discussions that are posted but can't quite figure out where I am going wrong in my code.
This is taskList.cpp.
The header file taskList.h is posted after it.
I'm using VS2013.
When I debug the error is posted at line 55 in the taskList.cpp file below
list = new Task[capacity];
#include "taskList.h"
#include "mytools.h"
TaskList::TaskList()
{
capacity = CAP;
list = new Task[capacity];
size = 0;
}
TaskList::TaskList(char filename[])
{
capacity = CAP;
list = new Task[capacity];
size = 0;
//load from file.
ifstream inData;
Task aTask;
char tempName[MAXCHAR];
char tempDescription[MAXCHAR];
char tempDate[MAXCHAR];
inData.open("task.txt");
if (!inData){
cout << "cannot open file";
exit(0);
}
inData.getline(tempName, MAXCHAR, ';');
while (!inData.eof())
{
inData.getline(tempDescription, MAXCHAR, '\n');
inData.getline(tempDate, MAXCHAR, '\n');
aTask.setName(tempName);
aTask.setDescription(tempDescription);
aTask.setDate(tempDate);
addTask(aTask);
inData.getline(tempName, MAXCHAR, ';');
}
inData.close();
;
TaskList::~TaskList()
{
if (list)
{
delete [] list;
list = NULL;
}
}
//Adds a video item to the list
void TaskList::addTask(Task aTask)
{
list[size++] = aTask;
}
//displays the list of videos
void TaskList::showList()
{
int i = 0;
for (i = 0; i < size; i++)
{
list[i].printTask();
}
}
void TaskList::searchList()
{
char searchName[MAXCHAR];
char tempName[MAXCHAR];
int i;
bool found = false;
cout << "Enter the name of the course to search for: ";
cin.getline(searchName, MAXCHAR);
for (i = 0; i < size; i++)
{
list[i].getName(tempName);
if (strstr(searchName, tempName) != NULL)
{
list[i].printTask();
found = true;
}
}
if (found == false)
cout << "No search results." << endl;
}
void TaskList::writeData()
{
ofstream outData;
outData.open("task.txt");
if (!outData)
{
cout << "cannot open file";
exit(0);
}
for (int i = 0; i < size; i++)
list[i].printToFile(outData);
outData.close();
}
//expand array function
void TaskList::expand()
{
char tempName[MAXCHAR];
char tempDescription[MAXCHAR];
char tempDate[MAXCHAR];
capacity += GROWTH;
Task *temp = new Task[capacity];
//copy from old array to new array
for (int i = 0; i < size; i++)
{
list[i].getName(tempName);
list[i].getDescription(tempDescription);
list[i].getDate(tempDate);
temp[i].setName(tempName);
temp[i].setDescription(tempDescription);
temp[i].setDate(tempDate);
}
//delete old array
delete [] list;
list = NULL;
//point ptr to temp
list = temp;
//set temp to NULL
temp = NULL;
}
The header file (taskList.h)
#include <iostream>
#include <fstream>
using namespace std;
const int CAP = 2;
const int GROWTH = 2;
//define class VideoList for array of Videos and its size.
class TaskList
{
private:
Task *list;
int size;
int capacity;
void expand();
public:
//constructors
TaskList();
TaskList(char filename[]);
//destructor
~TaskList();
//database functions
void addTask(Task aTask);
void showList();
void searchList();
void writeData();
};
#endif
Just to be sure that everything is made clear because there are 3 header files, 4 source files, and a text file, I am include the task.h header file and task.cpp source file.
Here is task.h:
#ifndef TASK_H
#define TASK_H
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string.h>
using namespace std;
const int MAXCHAR = 101;
class Task
{
private:
char *name;
char *description;
char *date;
public:
//defult constructor
Task();
//constructor with parameters
Task(char newName[], char newDescription[], char newDate[]);
//copy constructor
Task(const Task &otherTask);
//Accessor funct
void getName(char returnName[]);
void getDescription(char returnDescription[]);
void getDate(char returnDate[]);
//mutator function
void setName(char newName[]);
void setDescription(char newDescription[]);
void setDate(char newDate[]);
//print function to print a video
void printTask();
void printToFile(ofstream &outFile);
const Task& operator= (const Task& anItem);
};
#endif
Here is the task.cpp file, not sure if this is necessary but I am adding it for clarity:
#include "task.h"
#include <iostream>
using namespace std;
//defult constructor
Task::Task()
{
strcpy(name, "no course name");
strcpy(description, "no task description");
strcpy(date, "no due date");
}
//constructor with parameters
Task::Task(char newName[], char newDescription[], char newDate[])
{
name = new char[strlen(newName) + 1];
description = new char[strlen(newDescription) + 1];
date = new char[strlen(newDate) + 1];
strcpy(name, newName);
strcpy(description, newDescription);
strcpy(date, newDate);
}
//copy constructor
Task::Task(const Task &otherTask)
{
//allocate memory and then copy name
this->name = new char[strlen(otherTask.name) + 1];
strcpy(name, otherTask.name);
//allocate memory and then copy description
this->description = new char[strlen(otherTask.description) + 1];
strcpy(description, otherTask.description);
//allocate memory and then copy date
this->date = new char[strlen(otherTask.date) + 1];
strcpy(date, otherTask.date);
}
//Accessor functions
void Task::getName(char returnName[])
{
strcpy(returnName, name);
}
void Task::getDescription(char returnDescription[])
{
strcpy(returnDescription, description);
}
void Task::getDate(char returnDate[])
{
strcpy(returnDate, date);
}
//mutator functions
void Task::setName(char newName[])
{
strcpy(name, newName);
}
void Task::setDescription(char newDescription[])
{
strcpy(description, newDescription);
}
void Task::setDate(char newDate[])
{
strcpy(date, newDate);
}
//prints a video item
void Task::printTask()
{
cout << name << ';' << description << ';' << date << endl;
}
void Task::printToFile(ofstream &outFile)
{
outFile << name << ';' << description << ';' << date << endl;
}
//assignment operator overloaded
const Task& Task::operator= (const Task& aTask)
{
strcpy(this->name, aTask.name);
this->description = aTask.description;
strcpy(this->description, aTask.description);
this->date = aTask.date;
strcpy(this->date, aTask.date);
return *this;
}
Here is the problem:
char *name;
// ...
strcpy(name, "no course name");
The first line creates a pointer which currently does not point anywhere. Then you tell strcpy to copy that string to where the pointer is pointing, so it writes the string to "nowhere" (in practice: a semi-random memory location). This causes your access violation.
To fix this, replace the code with:
std::string name;
// ...
name = "no course name";
Do the same for description and date. Note that this means you don't need a copy-constructor or copy-assignment operator or destructor; because the default ones behave correctly.
Of course you will need to change your accssor functions (but they were badly designed anyway since the caller cannot prevent a buffer overflow):
std::string getName() const { return name; }
Also, change Task *list; to std::vector<Task> list; and stop using new and delete. The vector correctly manages memory for you.
It is simplest and easiest to do this task without using pointers or manual memory management or C-library functions such as strcpy. You'll halve your code size (at least) and it will be much less prone to error.
You may need #include <string> and #include <vector>.
Since the erroe happens at allocation if an array (list = new Task[capacity]) i guess your problem is in default constructor of Task class. try playing with this constructor a liitle , i suggest allocating yor char arrays (names , descriptions and data) befor filling them.
somecode like name = new Char[14]; (and of course same for the other two)
You have failed to follow the rule-of-five or the rule-of-zero.
The correct thing (rule-of-zero) would be to implement TaskList in terms of std::vector<Task>.
Seeing as your assignment demands that you use a "dynamic array", perhaps they don't want you to use std::vector. This means that you are stuck with manual memory management. This means that you need to correctly implement or remove the following functions:
//You have these
TaskList::TaskList();
TaskList::TaskList(char filename[]);
TaskList::~TaskList();
//You are missing these, this is your problem:
TaskList::TaskList(TaskList const &o); //Copy constructor
TaskList &TaskList::operator=(TaskList const &o); //Copy assignment
TaskList::TaskList(TaskList &&o); //Move constructor
TaskList &TaskList::operator=(TaskList &&o); //Move assignment
If you do not explicitly supply these functions, the compiler may automatically generate them, and the compiler-generated versions will be incorrect (for the situation where you are manually managing resources within TaskList), as they will do member-wise moves or copies, rather than copying or moving the underlying resources. When you then use these incorrect compiler-generated versions, your code will have strange behaviour.
For Task, you shouldn't be managing multiple resources at once. Use std::string, or otherwise write your own string class, and then use it to manage the string members of Task. If you do not, your code is almost guaranteed to be incorrect (due to a lack of exception safety).

overloaded assignment operator - char pointers not copying correctly

I have a class User that looks like this:
class User
{
private:
char* p_username;
int nProcesses;
struct time
{
int mins;
int secs;
} totalTime;
int longestPID;
char* p_longestPath;
public:
User();
User(const char[],int,int,int,const char[]);
~User();
User operator=(const User&);
// Other functions
};
And the overloaded assignment operator function is:
User User::operator=(const User &u)
{
if (this != &u)
{
delete [] p_username;
delete [] p_longestPath;
p_username = new char[strlen(u.p_username)+1];
strcpy(p_username,u.p_username);
nProcesses = u.nProcesses;
totalTime.mins = u.totalTime.mins;
totalTime.secs = u.totalTime.secs;
longestPID = u.longestPID;
p_longestPath = new char[strlen(u.p_longestPath)+1];
strcpy(p_longestPath,u.p_longestPath);
}
return *this;
}
A sample main program using the assignment operator:
int main()
{
cout << "\n\nProgram\n\n";
User u("Username",20,30,112233,"Pathname"),u2;
u2 = u;
}
When I try to use the assignment operator in the line u2 = u, everything is assigned properly except the dynamic char arrays.
Test output from the end of the operator= function shows that at the end of the assignment itself everything has works perfectly (the usernames and pathnames are correct), however test output from the main function directly after the assignment shows that all of a sudden the char arrays have changed. Suddenly the username of u2 is empty, and the first half of the pathname is garbage.
If at the end of the assignment operator function the username and pathname are perfect, how can they be wrong back in the calling function?
This really has me stumped...
Edit: Here are the constructors
User::User()
{
p_username = 0;
nProcesses = 0;
totalTime.mins = 0;
totalTime.secs = 0;
longestPID = -1;
p_longestPath = 0;
}
User::User(const char UID[],int minutes,int seconds,int PID,const char path[])
{
p_username = new char[strlen(UID)+1];
strcpy(p_username,UID);
nProcesses = 1;
totalTime.mins = minutes;
totalTime.secs = seconds;
longestPID = PID;
p_longestPath = new char[strlen(path)+1];
strcpy(p_longestPath,path);
}
You are returning by value from the assignment function. It is possible that your copy constructor is flawed.
You might want to check out this tutorial here:
http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html
Here is an example from there:
MyClass& MyClass::operator=(const MyClass &rhs) {
// Only do assignment if RHS is a different object from this.
if (this != &rhs) {
... // Deallocate, allocate new space, copy values...
}
return *this;
}