Using overloaded operator on container - c++

I have simple class which holds array of integers. I want to overload + to merge two ararys together. I have defined two overloadors. + and =
class Money{
Money & operator =( const Money &a )
{
for( int i = 0; i < size ;i++ ) arr[i] = a.arr[i];
return *this;
}
Money & operator +( const Mone &a )
{
Money temp;
for( int i = 0; i < size ;i++ ){
temp.arr[i] = arr[i] + a.arr[i];
}
return temp;
}
private:
int arr[50];
int size = 50;
}
The problem is index 0, it returns random number from memory . I have seen some question about similliar problem but with * operator ( i will try to find it and link it ), where i got my operator = from. What is causing this? I am invoking it as
Money a;
Money b;
Money d;
d = a + b;
// print array;
I am new to overloading so i have harder time analyzing and understaning concept.

The basic problem is here, and has nothing really to do with overloading:
Money & operator +( const Mone &a ) {
Money temp;
:
return temp;
The problem being that you return a reference to a local variable, which is destroyed when the function returns so is a dangling reference, leading to undefined behavior.
Change it to return Money by value.

As I understand the problem in operator + you are creating a temporary variable temp. That variable will live until the code of "operator+" is finished. As you are returning a reference to that variable id est essentially a hidden pointer to it when the code finishes that reference isn't any more valid. If instead you change the code and return by value everything should work correctly. Instead things work correctly for the =operator because the reference you return is tied to an object that will exist after the end of the "operator=" call.

Related

Why my destructor shows that pointer being freed was not allocated c++

I want to implement 2 array addition, but when a destructor to the class SList
void operator+(SList list2) {
int totalLen = this->len + list2.len;
char** temp = new char* [totalLen];
for(int i = 0; i < len; i++) {
temp[i] = this->list[i];
}
for(int i = len, j = 0; i < totalLen; i++, j++) {
temp[i] = list2.get(j);
}
delete[] this->list;
this->list = temp;
this->len = totalLen;
cout << len << endl << endl;
}
Here are the get method that just return the dynamic array of char:
char* get(int i) {
if (i >= len) {
return "";
} else {
return list[i];
}
}
here are my class SList private variables:
private:
char** list;
int len;
char* generateString(){
char* str;
int n = rand() % 20 + 1;
str = new char[n + 1];
for(int i = 0; i < n; i++) {
str[i] = 'a' + rand()%26;
}
str[n] = '\0';
return str;
};
~SList() {
delete[] list;
}
It always shows malloc error on the destructor.
malloc: *** error for object 0x105007410: pointer being freed was not allocated
malloc: *** set a breakpoint in malloc_error_break to debug
Please help! I have carefully checked my delete method on the dynamic allocated array, but it always shows this error.
I have tried to check other delete from the other function, but none of them make the same malloc error. I have tried to commented the destructor method and everything work fine. But i really need to have destructor method here. I hope someone with more expertise on c++ can help me fix this malloc error and gave an explanation on which part i made a mistake.
Regardless what are other details of implementation, the destructor is not correct while you're using a data structure known as a "ragged array", i.e. list is a pointer to an array of pointers. delete[] would free the pointer array, but not char arrays pointed by its elements. You have to do something like this:
~SList() {
if(!list) return; // if we cannot guarantee that list isn't
// nullptr we have to check it,
// or result of list[i] would be undefined.
for(int i = 0; i < len; i++)
delete[] list[i];
delete[] list;
}
and you have to make sure that any of those pointers is either initialized by new expression or is equal nullptr.. It doesn't happen on its own. You have to make sure during construction and all operations. You didn't show any. Look for faults there.
The method get() is a disaster waiting to happen and is ill-formed, i.e. it doesn't follow C++ rules. The string literal "" returns const char*, always the same one and the statement return ""; is incorrect - some compilers only warn about it though. It cannot be deallocated by delete.
char* get(int i) {
if (i >= len) {
return nullptr; // "" - is not safe
} else {
return list[i];
}
}
Deleting a nullptr is a safe no-op. Deleting something that was't returned by new is a disaster.
The addition operator is taking list2 by value, which means that proper copy operations have to be implemented. You didn't show them either. Default implementation would just copy a pointer and destruction of local copy would deallocate memory used by original via ~SList() above. The operator have to return resulting object and should not modify one pointed by this. You had implemented an operator+=. The way you did it, it would work as
a+b; // a now contains result of concatenation.
It's simply weird to use. Proper operator would be
SList operator+(SList& list2);
In general, an object that deals with ownership of some resource, dynamic memory in our case, have to implement certain set of special member functions:
~SList();
SList(const SList& other);
SList(SList&& other); // move copy, source is a temporal.
SList& operator=(const SList& other);
SList& operator=(SList&& other); // move assignment
If that is done right, you can safely do the c = a + b; assignment.
Note that if you pass argument by reference you have to take in account that arguments of assigning operators aren't referencing the object pointed by this and act accordingly if they are. Otherwise you would destroy it and loose original data. On other hand copying argument is excessive and user-unfriendly due to increased cost and memory footprint. Concatenation of n-element and m-element array is expected to have memory footprint of n+m elements , not n+2*m.

Constant pointers used in real-life

Dear Stackoverflow community
I am trying to understand pointers better and have come across a question:
Q: When can we use a constant pointer? Give an example with a real scenario and give some code.
I had a problem trying to find and understand where a constant pointer code be used in real-life and the code involved. I am not sure if my code meets the standard of my example. I tried the following:
My Answer:
1- Definition:
A constant pointer is a pointer that cannot change the address it is holding.
2- Example:
If you want to find a specific number stored in your phone`s contacts. Rather than duplicating your entire contacts list (and al its numbers) and then checking for that specific number. Just hold its address and check the original contacts list if the number is there.
3- Code:
int main(){
const int* number = 032 ... ;
bool found = false;
Vector<int> contactList = { 031 ... , 032 ... , 072 ... };
for(int i=0; i < contactList.size(); i++){
if( *number == contactList[i]){
valid = true;
}
}
if(valid){
cout<< "Number found"<<endl;
} else{
cout<< "Number NOT found"<<endl;
}
}
Firstly a const pointer and a pointer to const are different things:
a const pointer itself is const. It cannot be pointed to anything other than the thing it is already pointing to, be the thing it points to might be altered:
int i = 5;
int *const p1 = &i; // a const pointer
++*p1; // valid code. i is now 6
int j = 0;
p1 = &j; // error
a pointer to const itself may point to different things, but it assumes everything it points to is const, so it won't allow altering them:
int i = 5;
const int * p2 = &i; // a pointer to const
++*p2; // error
int j = 0;
p2 = &j; // valid code. p2 is now pointing to j
I assume your question is "Why would anyone use a pointer which assumes everything is const?". There may be many reasons. One of them is, when you see const int * as a function parameter, you know this function is not going to mess with your variable. It's going to stay the same after the function returns. This is essentially why we use const anyway. We could just not change variables instead, but by declaring them as const we know compiler is going to make sure our variables are not changed by mistake or misunderstanding or anything else.
Pointer to const or const pointer ?
You need to be careful about the way to define a const pointer. Because a const pointer is not a pointer to const.
static int table[10];
const int* number = table; // non const pointer to const
int * const number2 = table; // const pointer to non const
number++; // this is allowed because the pointer is not const
*number += 2; // this is NOT allowed because it's a pointer to const
number2++; // this is NOT allowed because the pointer is const
*number2 +=2; // this is allowed because the const pointer points to a non const
By the way, be careful with leading 0 since they mean octal notation:
cout << 032 <<endl; // displays 26 in decimal since 032 is octal notation
Pointers, addresses and values
Be aware of the difference between a pointer and the value pointed to. Fortunately C++ protects you in forbidding this:
const int* number = 032; // compiler error
If you want to keep a pointer to a specific value:
int myvalue=032;
const int* number = &myvalue; // ok as long as you remain in scope
Caution when pointing to vector elements
Last but not the least, if you'd be tempted to use a pointer to a vector element, be aware that the address of a vector element may change (and pointers be invalid) in certain cases, for example when the vector needs to grow.
Example of what you're trying to do
Now let's put all this together, and here a slightly modified program:
const int * number; // const to avoid accidental overwrite
int search; // value to search for
cout<<"What number are you looking for ? ";
cin>>search;
for(int i=0; i < contactList.size(); i++){
if( contactList[i] == search){ // compare values
number = &contactList[i]; // set pointer
found = true;
}
}
// if the vector is not modified, you may use the pointer.
if(found){
cout<< "Number found: "<< *number <<endl;
}
else{
cout<< "Number NOT found"<<endl;
}

Overloading + operator to concatenate two strings in C++ (Some doubts)

I have just started learning C++ a few days back. I was given an assignment to demonstrate + operator overloading to concatenate two strings. I came up with this solution:
#include <iostream>
using namespace std;
class Strcpy{
private:
char* wrd;
int len;
public:
Strcpy();
Strcpy(char* );
void Display();
friend Strcpy operator + (Strcpy, Strcpy);
friend Strcpy concatinator(Strcpy, Strcpy);
};
Strcpy :: Strcpy(){
wrd = '\0';
len = 0;
}
Strcpy :: Strcpy(char* w){
int i; len = 0;
for(i = 0; w[i] != '\0' ; i++)
len ++;
wrd = w;
}
void Strcpy :: Display(){
cout << "\nOutput: " << wrd << " "<< len;
}
Strcpy operator + (Strcpy obj1, Strcpy obj2){
Strcpy temp;
int i;
temp.wrd = new char[obj1.len + obj2.len];
temp = concatinator(temp, obj1);
temp = concatinator(temp, obj2);
temp.wrd[temp.len] = '\0';
return temp;
}
Strcpy concatinator(Strcpy obj, Strcpy temp){
for(int i = 0; temp.wrd[i] != '\0'; i++)
{
obj.wrd[obj.len] = temp.wrd[i];
obj.len++;
}
return obj;
}
int main(){
Strcpy word, word_I("Hello"), word_II("World");
word = word_I + word_II;
word.Display();
return 1;
}
Some things to be noted:
deprecated conversion from string constant to 'char*' [-Wwrite-strings] I realize this is being caused because I am converting an immutable type to a mutable one but what alternative approach can I try to get rid of this.
I want to avoid using friend functions, but the overloaded operator needs two arguments which isn't possible if it remains a class member.
The following line works the same even if it is changed, why is this happening:
temp.wrd = new char[obj1.len + obj2.len];
//changed to
temp.wrd = new char[//any number here];
I want avoid using string functions if that is possible at all.
Whenever i try taking an input in the following form, it crashes:
char* Strcpy :: get(){
char* temp;
cin >> temp;
return temp;
}
int main(){
Strcpy word;
Strcpy word_I(word.get()), word_II(word.get());
word = word_I + word_II;
word.Display();
return 1;
}
Lastly, I would appreciate any help that would help me improve on the existing solution and some explanation so as to why it is better and the mistakes I am making.
deprecated conversion from string constant to 'char*' [-Wwrite-strings] I realize this is being caused because I am converting an immutable type to a mutable one but what alternative approach can I try to get rid of this.
You never modify *w, so you can use a pointer to const instead.
I want to avoid using friend functions, but the overloaded operator needs two arguments which isn't possible if it remains a class member.
The first argument of a member operator overload is the implicit this pointer. If you declare Strcpy Strcpy::operator+(const Strcpy&) const, it will be a binary operator. That said, the friend operator is probably a better approach.
The following line works the same even if it is changed, why is this happening:
temp.wrd = new char[obj1.len + obj2.len];
//changed to
temp.wrd = new char[//any number here];
It will work as long as "any number" is large enough to contain the entire string. If you write outside of the bounds, the behaviour is undefined.
Whenever i try taking an input in the following form, it crashes:
char* temp;
cin >> temp;
The stream extraction operator requires that a char* passed to it must point to an array sufficiently large to contain the user input. You forgot to initialize temp, so the requirement is not satisfied. As a result, the behaviour of the program is undefined. Solution: Allocate some memory and initialize temp to point to that memory.
The same bug occurs the constructor Strcpy(char*). You don't initialize this->wrd, but you dereference it. Therefore the behaviour is undefined. The solution is the same as above.
If I understood this right
I want to avoid using friend functions, but the overloaded operator
needs two arguments which isn't possible if it remains a class member.
your statement is wrong.
Sample for a binary + operator in a class:
#include <iostream>
class Int {
private: int _i;
public:
Int(int i = 0): _i(i) { }
Int operator + (const Int &i) const
{
return Int(_i + i._i);
}
int get() const { return _i; }
};
int main(int, char**)
{
Int i1(1), i2(2);
Int i;
i = i1 + i2;
std::cout << "i: " << i.get() << std::endl;
return 0;
}
Compiled and tested with gcc on cygwin:
$ g++ -o test-op-plus test-op-plus.cc
$ ./test-op-plus.exe
i: 3

Pointer Passing and Parameters

I am having a problem in my code right now. I can't seem to get what I need and return the address of my structure "b" so other functions can use it. If you can help me out that would be great!
Here is my necessary code:
int notFound = 0;
int choiceNumber;
int arraySize;
Basketball * b;
b = readFile(arraySize, notFound, &b);
Here is the function that I am having the problems:
Basketball * readFile(int & arraySize, int & notFound, Basketball * &b)
{
ifstream inputFile;
inputFile.open("games.txt");
if(inputFile.fail())
{
cout << "The file name \"games.txt\" was not found!" << endl;
notFound = 1;
}
else
{
inputFile >> arraySize;
b = new Basketball [arraySize];
for (int i = 0; i < arraySize; i++)
{
inputFile >> b[i].visitTeam >> b[i].homeScore >> b[i].visitScore;
}
return & b;
}
}
My build errors are these:
Error: invalid intialization of non-const reference of type basketball*& from an rvalue of type Basketball**
Error: In passing arguement 3 of Basketball* readfile(int&,int&, Basketball*&)
Error: Cannot convert Basketball** to Basketball* in return
If you can point me in the right direction that would be great!
The variable b already is a pointer, using &b will create a pointer to the pointer. Drop the address-of operator &.
The error message is very clear about it, same with you returning a pointer to a pointer when you declared is a returning only a single pointer.
"return b;" is what yoy want, not "return &b"
&b Is the address of Basketball*, so you would end with incorrect Basketbal**
As others already wrote, since b is already a pointer, return b; will fix your error.
If you do return &b; you are returning the address of a pointer, i.e. a "double level indirection" pointer, which would be a Basketball**.
However, let me add that you may simplify your C++ code using more modern idioms, like using std::vector<Basketball> instead of raw pointers and raw arrays, e.g.:
std::vector<Basketball> readFile(int & notFound);
Note that a vector knows its own size (e.g. you can call its size() method to query for it), so you don't need a separate reference parameter to store the size.
And, moreover, a vector automatically cleans up its content, thanks to its destructor. So, you don't put a burden on the caller to make an explicit call to delete[] to release the allocated array.
As an alternative, you could use a bool parameter meaning "not found", and pass the vector as non-const reference, e.g.:
// Returns false if not found, true if found
bool readFile(std::vector<Basketball>& v);
Or, depending on your design, you may even return a std::vector, and throw an exception in the not-found case.

Meaning of *& and **& in C++

I found these symbols in a function declaration several times, but I don't know what they mean.
Example:
void raccogli_dati(double **& V, double **p, int N) {
int ultimo = 3;
V = new double * [N/2];
for(int i=0; i < N/2; i++) {
V[i] = new double[N/2], std :: clog << "digita " << N/2 - i
<< " valori per la parte superiore della matrice V: ";
for(int j=i; j < N/2; j++)
std :: cin >> V[i][j], p[ultimo++][0] = (V[i][j] /= sqrt(p[i][0]*p[j][0]));
}
for(int i=1; i < N/2; i++)
for(int j=0; j < i; j++)
V[i][j] = V[j][i];
}
That is taking the parameter by reference. So in the first case you are taking a pointer parameter by reference so whatever modification you do to the value of the pointer is reflected outside the function. Second is the simlilar to first one with the only difference being that it is a double pointer. See this example:
void pass_by_value(int* p)
{
//Allocate memory for int and store the address in p
p = new int;
}
void pass_by_reference(int*& p)
{
p = new int;
}
int main()
{
int* p1 = NULL;
int* p2 = NULL;
pass_by_value(p1); //p1 will still be NULL after this call
pass_by_reference(p2); //p2 's value is changed to point to the newly allocate memory
return 0;
}
First is a reference to a pointer, second is a reference to a pointer to a pointer. See also FAQ on how pointers and references differ.
void foo(int*& x, int**& y) {
// modifying x or y here will modify a or b in main
}
int main() {
int val = 42;
int *a = &val;
int **b = &a;
foo(a, b);
return 0;
}
That's passing a pointer by reference rather than by value. This for example allows altering the pointer (not the pointed-to object) in the function is such way that the calling code sees the change.
Compare:
void nochange( int* pointer ) //passed by value
{
pointer++; // change will be discarded once function returns
}
void change( int*& pointer ) //passed by reference
{
pointer++; // change will persist when function returns
}
An int* is a pointer to an int, so int*& must be a reference to a pointer to an int. Similarly, int** is a pointer to a pointer to an int, so int**& must be a reference to a pointer to a pointer to an int.
*& signifies the receiving the pointer by reference. It means it is an alias for the passing parameter. So, it affects the passing parameter.
#include <iostream>
using namespace std;
void foo(int *ptr)
{
ptr = new int(50); // Modifying the pointer to point to a different location
cout << "In foo:\t" << *ptr << "\n";
delete ptr ;
}
void bar(int *& ptr)
{
ptr = new int(80); // Modifying the pointer to point to a different location
cout << "In bar:\t" << *ptr << "\n";
// Deleting the pointer will result the actual passed parameter dangling
}
int main()
{
int temp = 100 ;
int *p = &temp ;
cout << "Before foo:\t" << *p << "\n";
foo(p) ;
cout << "After foo:\t" << *p << "\n";
cout << "Before bar:\t" << *p << "\n";
bar(p) ;
cout << "After bar:\t" << *p << "\n";
delete p;
return 0;
}
Output:
Before foo: 100
In foo: 50
After foo: 100
Before bar: 100
In bar: 80
After bar: 80
Typically, you can read the declaration of the variable from right to left. Therefore in the case of int *ptr; , it means that you have a Pointer * to an Integer variable int. Also when it's declared int **ptr2;, it is a Pointer variable * to a Pointer variable * pointing to an Integer variable int , which is the same as "(int *)* ptr2;"
Now, following the syntax by declaring int*& rPtr;, we say it's a Reference & to a Pointer * that points to a variable of type int. Finally, you can apply again this approach also for int**& rPtr2; concluding that it signifies a Reference & to a Pointer * to a Pointer * to an Integer int.
To understand those phrases let's look at the couple of things:
typedef double Foo;
void fooFunc(Foo &_bar){ ... }
So that's passing a double by reference.
typedef double* Foo;
void fooFunc(Foo &_bar){ ... }
now it's passing a pointer to a double by reference.
typedef double** Foo;
void fooFunc(Foo &_bar){ ... }
Finally, it's passing a pointer to a pointer to a double by reference. If you think in terms of typedefs like this you'll understand the proper ordering of the & and * plus what it means.
This *& in theory as well as in practical its possible and called as reference to pointer variable. and it's act like same.
This *& combination is used in as function parameter for 'pass by' type defining. unlike ** can also be used for declaring a double pointer variable.
The passing of parameter is divided into pass by value, pass by reference, pass by pointer.
there are various answer about "pass by" types available. however the basic we require to understand for this topic is.
pass by reference --> generally operates on already created variable refereed while passing to function e.g fun(int &a);
pass by pointer --> Operates on already initialized 'pointer variable/variable address' passing to function e.g fun(int* a);
auto addControl = [](SomeLabel** label, SomeControl** control) {
*label = new SomeLabel;
*control = new SomeControl;
// few more operation further.
};
addControl(&m_label1,&m_control1);
addControl(&m_label2,&m_control2);
addControl(&m_label3,&m_control3);
in the above example(this is the real life problem i came across) i am trying to init few pointer variable from the lambda function and for that we need to pass it by double pointer, so that comes with d-referencing of pointer for its all usage inside of that lambda + while passing pointer in function which takes double pointer, you need to pass reference to the pointer variable.
so with this same thing reference to the pointer variable, *& this combination helps. in below given way for the same example i have mentioned above.
auto addControl = [](SomeLabel*& label, SomeControl*& control) {
label = new SomeLabel;
control = new SomeControl;
// few more operation further.
};
addControl(m_label1,m_control1);
addControl(m_label2,m_control2);
addControl(m_label3,m_control3);
so here you can see that you neither require d-referencing nor we require to pass reference to pointer variable while passing in function, as current pass by type is already reference to pointer.
Hope this helps :-)