c++ Copy constructors and destructors - c++

I am learning constructors and Destructors in c++; Help me grasp my mistakes even if they are silly...
HERE is a code I have written to perform addition using classes in c++; This creates two summands of datatype num and employs the constructor sum() to perform sum of the two numbers; However when everything was goin' alright, I stumbled upon creating a copy constructor for num , (Although not necessary but still for practice)... without the dynamic object of the class sum it is not possible to run the code anyway(without removing the copy constructor)... Help me improve my code and my mistakes in the code below; Also I wanna know how to make use of the copy constructor in this program; the problem being that in the destructor the delete operation is being performed multiple times on the same piece of memory (I suppose)
Here's my Code
#include<iostream>
#include<new>
using namespace std;
class num
{
public:
int *a;
num(int x)
{
try
{
a=new int;
}
catch(bad_alloc xa)
{
cout<<"1";
exit(1);
}
*a=x;
}
num(){ }
num(const num &ob)
{
try
{
a=new int;
}
catch(bad_alloc xa)
{
cout<<"1''";
exit(2);
}
*a=*(ob.a);
}
~num()
{
cout<<"Destruct!!!";
delete a;
}
};
class sum:public num
{
public:
int add;
sum(num n1,num n2)
{
add=*(n1.a)+*(n2.a);
}
int getsum()
{
return add;
}
};
int main()
{
num x=58;
num y=82;
sum *s=new sum(x,y);
cout<<s->getsum();
delete s;
return 0;
}

I may miss something - didn't use new/delete for too long, but tried to correct all what I noticed.
P.S. always use smart pointers.
#include <iostream>
#include <exception>
#include <new>
using namespace std;
int* allocate(const char* err_msg, int exit_code)
{
int* a = nullptr;
try
{
a = new int;
}
catch (bad_alloc&)
{
cout << err_msg << endl;
exit(exit_code);
}
return a;
}
class num
{
int* a = nullptr; // always should be initialized here
public:
num() noexcept : a(nullptr) // or here
{}
/*explicit*/ num(int x) : a(allocate("1", 1))
{
*a = x;
}
num(const num& ob) : a(allocate("1''", 2))
{
*a = *(ob.a);
}
// rule of zero/three/five
// default copy assignment will copy pointer and one int will be leaked and one will be deleted twice
num& operator =(const num& ob)
{
if (&ob == this)
{
return *this;
}
*a = *(ob.a);
return *this;
}
~num()
{
cout << "Destruct!!!";
delete a;
a = nullptr; // usefull for debug
}
int value() const
{
if (a == nullptr)
{
throw runtime_error("a == nullptr");
}
return *a;
}
};
class sum
{
int add = 0;
public:
sum(const num& n1, const num& n2)
{
add = n1.value() + n2.value();
}
int getsum() const
{
return add;
}
};
int main()
{
const num x = 58;
const num y = 82;
const sum* s = new sum(x, y);
cout << s->getsum() << endl;
delete s;
return 0;
}

Related

Assignment and retrieval using subscript and equals operator overloads

I've been having a hell of a time trying to solve this. What I am trying to do is use operator overloading so that my objects behave more like a multi dimensional array. I've found solutions to several of the smaller problems involved in making this happen but whenever I try to put it all together there is one issue or another, either lvalue assignment error or invalid initialization from rvalue or just straight up seg fault. I would appreciate any advice TY.
#include <iostream>
#include <vector>
#include <string>
class Matrix {
std::string **m;
public:
Matrix(int x, int y) {
m = new std::string*[x];
for (int i = 0; i < x; i++)
m[x] = new std::string[y];
}
class Proxy {
std::string *mm;
int lastIndex = 0;
public:
Proxy(std::string *s) : mm(s) {}
std::string &operator[](int index) {
lastIndex = index;
return mm[index];
}
std::string &operator=(std::string s) {
mm[lastIndex] = s;
return mm[lastIndex];
}
};
Proxy operator[](int index) {
return Proxy(m[index]);
}
};
int main()
{
Matrix *m = new Matrix(5, 5);
m[2][2] = std::string("It Works");
std::cout << m[2][2] << std::endl;
return 0;
In main(), m is a pointer to a Matrix object, so you need to dereference the pointer in order to access the Matrix object so you can invoke your Matrix::operator[] on it, eg:
int main()
{
Matrix *m = new Matrix(5, 5);
(*m)[2][2] = "It Works";
std::cout << (*m)[2][2] << std::endl;
delete m;
return 0;
}
Online Demo
Otherwise, the pointer is not really needed in your example to begin with, eg:
int main()
{
Matrix m(5, 5);
m[2][2] = "It Works";
std::cout << m[2][2] << std::endl;
return 0;
}
Online Demo
Either way, your Proxy does not need to implement operator= at all, eg:
class Proxy {
std::string *mm;
public:
Proxy(std::string *s) : mm(s) {}
std::string& operator[](int index) {
return mm[index];
}
};
A statement like m[2][2] = "..."; will not invoke your Proxy::operator=, it will invoke only Proxy::operator[]. A statement like m[2] = "..."; would be needed to invoke Proxy::operator=, which doesn't make sense to do in a multi-dimensional scenario.
Also, your Matrix constructor has a bug - writing to m[x] is going out of bounds of the m[] array, so the array is not actually filled at all, and you are corrupting surrounding memory, and leaking memory. You need to write to m[i] instead:
//m[x] = new std::string[y];
m[i] = new std::string[y];
After fixing that, Matrix is still leaking memory, as it does not implement a destructor to free the std::strings. You must delete[] anything you new[] (same with delete and new).
And then, you should finish off implementing support for the Rule of 3/5/0, by implementing a copy constructor and a copy assignment operator (your example code does not need them, but production code should always have them), eg:
#include <iostream>
#include <string>
#include <utility>
class Matrix {
std::string **m;
int m_x, m_y;
public:
Matrix(int x = 0, int y = 0) : m_x(x), m_y(y) {
m = new std::string*[x];
for (int i = 0; i < x; ++i)
m[i] = new std::string[y];
}
Matrix(const Matrix &src) : m_x(src.m_x), m_y(src.m_y) {
m = new std::string*[m_x];
for (int i = 0; i < m_x; ++i) {
m[i] = new std::string[m_y];
for (int j = 0; j < m_y; ++j) {
m[i][j] = src.m[i][j];
}
}
}
~Matrix() {
for (int i = 0; i < m_x; ++i)
delete[] m[i];
delete[] m;
}
Matrix& operator=(const Matrix &rhs) {
if (&rhs != this) {
Matrix temp(rhs);
std::swap(m, temp.m);
std::swap(m_x, temp.m_x);
std::swap(m_y, temp.m_y);
}
return *this;
}
class Proxy {
std::string *mm;
public:
Proxy(std::string *s) : mm(s) {}
std::string& operator[](int index) {
return mm[index];
}
};
Proxy operator[](int index) {
return Proxy(m[index]);
}
};
int main()
{
Matrix m(5, 5);
m[2][2] = "It Works";
std::cout << m[2][2] << std::endl;
Matrix m2(m);
std::cout << m2[2][2] << std::endl;
Matrix m3;
m3 = m2;
std::cout << m3[2][2] << std::endl;
return 0;
}
Online Demo
However, rather than using new[] manually, consider using std::vector instead (which you are already aware of, since you have #include <vector> in your code). This way, the Rule of 3/5/0 can be handled entirely by the compiler for you. std::vector and std::string are both fully compliant with the Rule, and so any compiler-generated destructor, copy constructor, and copy-assignment operator in Matrix will suffice, eg:
#include <iostream>
#include <vector>
#include <string>
class Matrix {
std::vector<std::vector<std::string>> m;
public:
Matrix(int x = 0, int y = 0) {
m.resize(x);
for (int i = 0; i < x; ++i)
m[i].resize(y);
}
class Proxy {
std::vector<std::string> &mm;
public:
Proxy(std::vector<std::string> &s) : mm(s) {}
std::string& operator[](int index) {
return mm[index];
}
};
Proxy operator[](int index) {
return Proxy(m[index]);
}
};
Online Demo

Strange copy constructor and destructor error

I have a class and i keep getting some error from the destructor.
This is the clas:
#pragma once
class Number
{
int bas;
char* val;
public:
Number(const char* value, int base);
Number(const Number& x);
~Number();
void SwitchBase(int newBase);
void Print();
int GetDigitsCount();
int GetBase();
};
This is the cpp file:
#include "Number.h"
#include <iostream>
Number::Number(const char* value, int base)
{
int a = -1;
do
{
a++;
} while (value[a] != '\0');
val = new char[a + 1];
for (int i = 0; i <= a; i++)
val[i] = value[i];
bas = base;
}
Number::Number(const Number& x)
{
int a = -1;
bas = x.bas;
do
{
a++;
} while (x.val[a] != '\0');
delete[]val;
val = new char[a + 1];
int i;
for (i = 0; i <= a; i++)
val[i] = x.val[i];
}
Number::~Number()
{
delete[]val;
}
void Number::Print()
{
std::cout << "Numarul este: " << val<< std::endl << "Baza este: " << bas<<std::endl;
}
int Number:: GetDigitsCount()
{
int l = 0;
do
{
l++;
} while (val[l] != '\0');
return l;
}
This is the main:
int main()
{
Number x("123", 10),y("111",10),z("0",10);
z = y;
z.Print();
}
I keep getting this error:
Invalid address specified to RtlValidateHeap( 010C0000, 010C8DD8 )
If i do this change in main it works properly but it is not really what I want...
int main()
{
Number x("123", 10),y("111",10);
Number z = y;
z.Print();
}
How can I solve this? I can't figure it out...
Your Number class is missing an assignment operator. Since you use the assignment operator in main the default assignment operator will cause a double delete when you exit main and this explains the error.
It also explains why the error goes away when you change main to use the copy constructor instead of the assignment operator.
You should look at the copy and swap idiom to show how to easily and efficiently implement copy constructors and assignment operators.
Alternatively you could also use std::string instead of manually allocating memory. This would eliminate the need to write a destructor, copy constructor and assignment operator. That's the best solution.
This is an example of how code may look like using std::string:
#include <iostream>
#include <string>
class Number
{
int bas;
std::string val;
public:
Number(std::string, int base);
Number(const Number& number);
Number& operator= (const Number& number);
~Number()=default;
void Print();
int GetDigitsCount();
};
Number::Number(std::string value, int base)
{
val=value;
bas=base;
}
Number::Number(const Number& number)
{
val=number.val;
bas=number.bas;
}
Number& Number::operator= (const Number& number)
{
val=number.val;
bas=number.bas;
return *this;
}
void Number::Print()
{
std::cout << "Numarul este: " << val<< std::endl << "Baza este: " << bas<<std::endl;
}
int Number:: GetDigitsCount()
{
return val.size();
}
int main()
{
Number x("123", 10),y("111",10),z("0",10);
Number k(y);
k.Print();
}

too many parameters for this operator function

First, I'm not good at english and also first time in StackOverflow, but I try to explain about my code's problem.
I was asked to make my own Vector(similar thing) from my professer, and there's a problem in fuction which returns a reference to the element at the requested position in the vector container. If the requested position is out of range, it should output some messages and terminate the program.
I should make this to Operator overloading, and this is my code.
double operator [](int n, const MyDoubleVector& _mV)//The arror come out at this line.
{
if(n > num)//'num' is private reference in class to count array. it typed int.
{
return 0;
}
return &_mV.data[n];//'data' is private reference in class. It declare like 'double *data = new double [num];'
}
I saw that sometimes 'friend' solve this, but when I put 'friend' in this line, it said me like "operator[] must be a member function."
Finally, Ihave no idea how to do. Would you please help me?
You need to implement the overload of operator[] as a member function of your class MyDoubleVector.
Here's the definition :
double & MyDoubleVector::operator[](int index);
operator [] must be defined as a member of the class.
example:
#include <iostream>
#include <cstdlib>
#include <algorithm>
struct MyDoubleVector
{
MyDoubleVector()
{}
MyDoubleVector(MyDoubleVector const& other)
{
// very naiive copy constructor
if (other.data)
{
std::for_each(other.data, other.data + other.num, [&](double val)
{
this->push(val);
});
}
}
MyDoubleVector& operator=(MyDoubleVector const& other)
{
auto temp = other; // invoke copy constructor
std::swap(num, temp.num);
std::swap(capacity, temp.capacity);
std::swap(data, temp.data);
return *this;
}
~MyDoubleVector()
{
delete [] data;
}
double& operator [](int n);
/** either define the method inline like this...
{
if(n > num)
{
std::cerr << "MyDoubleVector::operator[]: index " << n << " out of range" << std::endl;
std::exit(100);
}
return data[n];
}
**/
void push(double val)
{
if (num == capacity)
{
more();
}
data[num++] = val;
}
private:
void more()
{
if (!data)
{
data = new double [10];
capacity = 16;
}
else
{
auto newcapacity = capacity * 2;
auto newdata = new double [newcapacity];
std::copy(data, data + capacity, newdata);
std::swap(data, newdata);
capacity = newcapacity;
delete [] newdata;
}
}
int num = 0;
int capacity = 0;
double* data = nullptr;
};
/** ...
** or out of line like this
**/
double& MyDoubleVector::operator [](int n)
{
if(n > num)
{
std::cerr << "MyDoubleVector::operator[]: index " << n << " out of range" << std::endl;
std::exit(100);
}
return data[n];
}
int main()
{
MyDoubleVector v;
v.push(10.0);
v[1];
}

Writing an accessor method for inherited class with sparse member data?

Say I have a simple vector class, vec:
#include <iostream>
#include <stdlib.h>
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
double & operator[](int i) const {
check_index(i);
return data[i];
}
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
Now suppose I have a special type of vector with sparse structure, e.g., where every even-index is zero. Call this oddvec. Instances of oddvec should be declared just as with the vec class, but underneath, the memory use should be efficient since only half the data is non-zero.
The accessor for the oddvec class should return 0 if the index is even, and return the odd-index element (stored sequentially) otherwise. There a couple problems with this:
The double & return type is violated if the index is even, since the constant value, 0, is returned.
It's not clear to me how to handle the situation when an even index element is used as an lvalue. E.g., v[0] = 3.0 should not be allowed in the oddvec class, but is perfectly acceptable in the vector class. We can't simply throw an error when even indexes are used, because even indexes are fine as long as the intention is as an rvalue.
How do I design the accessor function for the oddvec class, while both keeping the memory storage efficient and inheriting all the methods from the parent?
Non-working example of oddvec:
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor (doesn't work!)
double & operator[](int i) const {
check_index(i);
if (i%2 == 0)
return 0;
else
return data[(i-1)/2];
}
};
Upon compilation:
main.cpp: In member function ‘double& oddvec::operator[](int) const’:
main.cpp:49:20: error: invalid initialization of non-const reference of type ‘double&’ from an rvalue of type ‘double’
return 0;
Working example using proxy classes:
I have implemented a proxy class as suggested in the answer below.
proxies.h
#ifndef PROXIES_H
#define PROXIES_H
#include <iostream>
#include <stdlib.h>
class proxy {
public:
proxy(int i, double v, double * d) {
index = i;
value = v;
data = d;
}
void operator=(double rhs) {
data[index] = rhs;
}
friend std::ostream & operator<<(std::ostream & outs, const proxy & p) {
outs << p.value;
return outs;
}
protected:
int index;
double value;
double * data;
};
class oddproxy : public proxy {
public:
oddproxy(int i, int v, double * d) : proxy(i, v, d) {}
void operator=(double rhs) {
if (index%2 == 0) {
std::cerr << "Even entries of oddvec are not assignable.\n";
exit(1);
}
data[index/2] = rhs;
}
};
#endif
vectors.h
#ifndef VECTORS_H
#define VECTORS_H
#include "proxies.h"
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
proxy operator[](int i) const {
check_index(i);
return proxy(i, data[i], data);
}
inline int length() const { return len; }
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor.
oddproxy operator[](int i) const {
check_index(i);
return oddproxy(i, (i%2 == 0) ? 0 : data[i/2], data);
}
};
#endif
main.cpp
#include <iostream>
#include "vectors.h"
int main () {
int N = 5;
vec V(N);
oddvec O(N);
for(int i=0; i < V.length(); i++) {
V[i] = i;
if(i%2 != 0) {
O[i] = i;
}
}
for(int i=0; i < O.length(); i++) {
std::cout << "V[" << i << "]=" << V[i] << ", "
<< "O[" << i << "]=" << O[i] << "\n";
}
O[0] = 13;
return 0;
}
output
V[0]=0, O[0]=0
V[1]=1, O[1]=1
V[2]=2, O[2]=0
V[3]=3, O[3]=3
V[4]=4, O[4]=0
Even entries of oddvec are not assignable.
You can use proxy object to do this.
simple sample code:
#include <iostream>
#include <vector>
using namespace std;
class very_odd_vector{
public:
class only_odd_proxy;
friend class only_odd_proxy;
only_odd_proxy operator [](int index);
int operator [](int index)const{return index%2==0?0:content[index/2];}
unsigned int size()const{return content.size()*2;}
private:
vector<int> content{1,3,5,7,9};
};
class very_odd_vector::only_odd_proxy{
public:
only_odd_proxy(very_odd_vector& vec,int index):vec(vec),index(index){}
operator int(){return index%2==0 ? 0 : vec.content[index/2];}
only_odd_proxy& operator =(int value){
if(index%2==0)
cout << "BAD OPERATION";//any error you want
else
vec.content[index/2] = value;
return *this;
}
private:
very_odd_vector& vec;
int index;
};
auto very_odd_vector::operator [](int index)->only_odd_proxy{return only_odd_proxy(*this,index);}
int main(){
very_odd_vector v;
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
cout << "writting value\n";
for(int i=0;i<v.size();++i){
cout << i << ':';
v[i]=10;
cout << '\n';
}
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
}
Edit for updated part of question :
I think this class will fit your need more.
//Both base and inherit class return this class
class maybe_readonly_proxy {
public:
maybe_readonly_proxy(double* data, bool readonly):readonly(readonly),data(data){}
maybe_readonly_proxy& operator=(double rhs) {
if(readonly){/*whatever error*/}
else {*data = rhs;}
return *this;
}
operator double()const{return *data;}
private:
bool readonly;
double * data;
};
You may need a variable to contain readonly (0 in this case) value, or modify the operator double() the check readonly state
Or just implement get and set method separately and do not use this proxy may be another choice.

Memory leak in code snippet

I'm trying to dust off my C++. I knocked together a simple program to find the Fibonacci sequence with memoization. There's a memory leak, and I can't seem to figure out why. The leak is reported in Fibonacci::setToFind.
Sorry for the long code chunk, but I couldn't figure out how to make a more minimal reproducible example.
#include <iostream>
class Fibonacci
{
public:
int m_valuefound;
int m_tofind;
long int *m_memo;
int findValue(int value){
if (m_memo[value] == 0) {
if (value == 0 || value == 1) {
m_memo[value] = 1;
} else {
m_memo[value] = findValue(value-1) + findValue(value-2);
}
}
return m_memo[value];
}
void setToFind(int value){
m_tofind = value;
m_memo = new long int[value];
std::fill_n(m_memo,value,0);
}
void solve(){
int value = m_tofind;
int result = findValue(value);
std::cout<< "Value is: " << result << std::endl;
}
~Fibonacci(){};
};
int main (int argc, char * const argv[]) {
std::cout << "Enter integer values until you'd like to quit. Enter 0 to quit:";
int user_ind=0;
// for testing non-interactivly
while(true){
for (user_ind=1; user_ind<45; user_ind++) {
Fibonacci *test = new Fibonacci;
test->setToFind(user_ind);
test->solve();
delete test;
}
}
return 0;
}
You never delete m_memo in the destructor of Fibonacci.
Since you're allocating m_memo as an array, you should delete with delete[] m_memo
Here is working code with a non-copyable Fibonacci class. Why don't
you allocate the memory in the constructor. Use RAII wherever possible
and remember The Rule of Five. Avoid all of this in the first place by
using std::vector.
#include <iostream>
class Fibonacci
{
public:
int m_valuefound;
int m_tofind;
long int *m_memo;
int findValue(int value){
if (m_memo[value] == 0) {
if (value == 0 || value == 1) {
m_memo[value] = 1;
} else {
m_memo[value] = findValue(value-1) + findValue(value-2);
}
}
return m_memo[value];
}
void setToFind(int value){
m_tofind = value;
m_memo = new long int[value];
std::fill_n(m_memo,value,0);
}
void solve(){
int value = m_tofind;
int result = findValue(value);
std::cout<< "Value is: " << result << std::endl;
}
// why don't you allocate in the constructor?
Fibonacci() : m_valuefound(0), m_tofind(0), m_memo(nullptr) {}
~Fibonacci() {
delete[] m_memo;
};
// make the class non-copyable
Fibonacci(const Fibonacci&) = delete;
const Fibonacci& operator=(const Fibonacci&) = delete;
/*
C++03 non-copyable emulation
private:
Fibonacci(const Fibonacci&);
const Fibonacci& operator=(const Fibonacci&);
*/
};
You are allocating m_memo in setToFind:
m_memo = new long int[value];
but your destructor does not have a delete [] m_memo. You should initialize m_memo in your constructor and make you class non-copyable by disabling your copy constructor and assignment operator using delete if using C++11:
Fibonacci(const Fibonacci&) = delete;
const Fibonacci& operator=(const Fibonacci&) = delete;
Otherwise you can make them private. If you used a container such as std::vector your life would be much simpler.
I suggest you use more the STL algorithms. Here's a code snippet with a rather not optimized functor but you can get the idea of the power of the STL:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
class Fibonacci
{
public:
Fibonacci();
~Fibonacci() {}
int operator()();
private:
int n0_;
int n1_;
int n_;
};
Fibonacci::Fibonacci():n0_(0),n1_(1),n_(0)
{
}
int Fibonacci::operator()()
{
if(n_ > 1)
return (++n0_) + (++n1_);
else
return ++n_;
}
using namespace std;
int main()
{
Fibonacci func;
vector<int> v;
//generate 100 elements
generate_n(v.begin(),100,func);
//printing the values using a lambda expression
for_each(v.begin(),v.end(),[](const int val){cout << val << endl;});
return 0;
}
You can then apply the finding algorithm you want on the vector using find_if and defining your own functor.