C++ private member of object is modified when calling constructor again - c++

I've created a class in C++ to deal with arrays of 0s and 1s. In private attributes I have a size, a type and an array of integer for the size specified.
My problem is that the values in the array is being modified every time I call the constructor again. In more detailled, I create a first object with the constructor, then a second one and doing this modifies the first one!
I've tried to play around with pointers, the new operator, const pointers to const object, nothing works! Idependently of the size of array I chose, it's always the third, then the sixth, then the ninth, etc value of the array that is modified to the value of the size.
any suggestion appreciated.
some extracts from my code:
class SArray
{
private:
int SArray_Size;
int DType;
int Table[];
public:
//complete constructor
SArray::SArray(const int& tsize, const int& ttype)
{
SArray_Size = tsize;
DType = ttype;
if (ttype == 0) //random array with integer values between 0 and 1
{
for (int i = 0; i < getSize(); i++)
{
Table[i] = rand() % 2;
}
}
if (ttype == 1) //default array with only 1s
{
for (int i = 0; i < getSize(); i++)
{
Table[i] = 1;
}
}
}
};
int main()
{
const int NbRes = 15;
//reset the random number generator
srand(time(0));
const SArray test3(NbRes,1);
(test3).print();
const SArray test1(NbRes,1);
(test1).print();
(test3).print();
return 0;
}

The culprit is int Table[] - you have not specified how large your table is.
You should really replace it with std::vector<int> Table; and initialize it with tsize.
For instance:
#include <vector>
class SArray
{
private:
int DType;
std::vector<int> Table;
public:
const size_t getSize() const { return Table.size(); }
public:
SArray::SArray(const int tsize, const int ttype) :
DType(ttype), Table(tsize)
{
int i, n = getSize();
switch( ttype )
{
case 0:
for (i = 0; i < n; ++i)
Table[i] = rand() % 2;
break;
case 1:
for (i = 0; i < n; ++i)
Table[i] = 1;
break;
}
}
};

You must allocate memory for "Table". For example:
SArray::SArray(const int& tsize, const int& ttype)
{
SArray_Size = tsize;
DType = ttype;
Table= new int[tsize];
...
Don't forget to free it in destructor.

Related

How to pass an array of structure by reference for sorting?

In this code , I am creating an array of structure and trying to sort the structure array based on "arr_time" field. I am having problem on how to pass the structure array by reference in function sort_process() .
#include<iostream>
using namespace std;
struct process {
public:
int p_id,arr_time,burst_time,comp_time;
};
void sort_process( process x[],int len)
{
int i,j;
process temp;
for(i=0;i<len;i++)
{
for(j=0;j<len-1;j++)
{
if(x[j].arr_time > x[j+1].arr_time)
{
temp = x[j];
x[j] = x[j+1];
x[j+1] = temp;
}
}
}
}
int main()
{
int n,i=0,j=0,k=0,t=0,flag;
cout<<"\n Enter number of processes : ";
cin>>n;
process p[n];
for(i=0;i<n;i++)
initialize(p[i]);
sort_process(p,n);
return 0;
}
You can simply use std::sort in the header <algorithm>:
std::sort(p, p+n, [](const process & p1, const process & p2){return p1 < p2}); // Will sort p in ascending order
But if you really want to do it manually and pass the array to a function, you can create the function as:
void sort_process(process * x, std::size_t len) // copy the pointer
{
std::sort(x, x+len, [](const process & p1, const process & p2){return p1 < p2;});
}
But passing process x[] as you did is equivalent.
Note: As we refer to an array by the pointer to its first element, what your are passing here is a pointer to the first element too (and not the array).
If you really want to pass it by reference, you can do it as follows:
void sort_process(process * const & x, std::size_t len)
{
std::sort(x, x+len, [](const process & p1, const process & p2){return p1 < p2;});
}
I added a const qualifier to forbid the modification of the pointer as it is not a copy but a reference to the original one
But you don't really gain anything by passing a reference here in my opinion.
Seems like you are afraid of dynamic arrays and pointers. Try this:
#include<iostream>
using namespace std;
struct process
{
int p_id, arr_time, burst_time, comp_time;
void initialize()
{
p_id = arr_time = burst_time = comp_time = 0;
}
process()
{
p_id = arr_time = burst_time = comp_time = 0;
}
~process() {}
};
void sort_process(process*& x, int len)
{
int i, j;
process temp;
for (i = 0; i < len; i++)
{
for (j = 0; j < len - 1; j++)
{
if (x[j].arr_time > x[j + 1].arr_time)
{
temp = x[j];
x[j] = x[j + 1];
x[j + 1] = temp;
}
}
}
}
int main()
{
int n, i = 0, j = 0, k = 0, t = 0, flag;
cout << "\n Enter number of processes : ";
cin >> n;
process* p = new process[n];
for (i = 0; i < n; i++)
p[i].initialize();
sort_process(p, n);
for (i = 0; i < n; i++)
p[i].~process();
delete[] p; p = 0;
return 0;
}

Copy Constructor And Operator Overloading +

class SmallVector
{
public:
SmallVector(void);
SmallVector( const int *tempArr, int arrSize );
SmallVector( const SmallVector &tempObj );
int size(void) const;
int capacity(void) const;
void push_back(int number); // ++
void push_back(int *tempArr, int arrSize ); // ++
int pop_back(void);
int operator[](int index) const;
SmallVector operator+(const SmallVector &tempObj);
SmallVector operator*(int times);
void printObj(void) const;
bool isFull(void);
private:
int staticIndex; // It refers to total element in the static part of the vector
int dynamicIndex; // it refers to index number of dynamic array(it also refers to number of elements in dynamic section)
int dynamicSize; // allocated memory for dynamic array
int staticArray[32];
int *dynamicArray;
void expand(int newSize);
void shrink(void);
};
SmallVector SmallVector::operator+(const SmallVector &tempObj)
{
int i;
int totalSize = ( this->size() + tempObj.size() );
if( totalSize == 0 ) // arguments of sum operator are empty vector
return SmallVector(); // default constructor is executed
int *tempArray = new int[totalSize];
for(i = 0; i < this->size(); ++i)// filling tempArray with first operand
{
if(i <= 31)
tempArray[i] = staticArray[i];
else
tempArray[i] = dynamicArray[i - 32];
}
for(int j = 0; j < tempObj.size(); ++j, ++i)
tempArray[i] = tempObj[j];
return SmallVector(tempArray, totalSize); // error is here
}
SmallVector::SmallVector( const SmallVector &tempObj )
{ // copy constructor
staticIndex = 0;
dynamicIndex = 0;
dynamicSize = 0;
if( tempObj.size() > 32 ){
dynamicSize = tempObj.size() - 32;
dynamicArray = new int[dynamicSize];
}
for( int i = 0; i < tempObj.size(); ++i ){
if( i <= 31 ){ // filling static array
staticArray[staticIndex] = tempObj[i];
++staticIndex;
}
else{
dynamicArray[dynamicIndex] = tempObj[i];
++dynamicIndex;
}
}
}
This is actually realizing a vector project ,but I encountered very interesting problem. If argument of copy constructor is not const, operator overloading + gives me an error when returning temporary instance of the class. I think, the compiler is confused about the constructors.
Error : no matching function for call to SmallVector::SmallVector(SmallVector&)
this error occurs in return statements in operator overloading +.

How to avoid returning pointers in a class

Assume I have a class A that has say 3 methods. So the first methods assigns some values to the first array and the rest of the methods in order modify what is computed by the previous method. Since I wanted to avoid designing the methods that return an array (pointer to local variable) I picked 3 data member and store the intermediate result in each of them. Please note that this simple code is used for illustration.
class A
{
public: // for now how the class members should be accessed isn't important
int * a, *b, *c;
A(int size)
{
a = new int [size];
b = new int [size];
c = new int [size];
}
void func_a()
{
int j = 1;
for int(i = 0; i < size; i++)
a[i] = j++; // assign different values
}
void func_b()
{
int k = 6;
for (int i = 0; i < size; i++)
b[i] = a[i] * (k++);
}
void func_c()
{
int p = 6;
for int (i = 0; i < size; i++)
c[i] = b[i] * (p++);
}
};
Clearly, if I have more methods I have to have more data members.
** I'd like to know how I can re-design the class (having methods that return some values and) at the same time, the class does not have the any of two issues (returning pointers and have many data member to store the intermediate values)
There are two possibilities. If you want each function to return a new array of values, you can write the following:
std::vector<int> func_a(std::vector<int> vec){
int j = 1;
for (auto& e : vec) {
e = j++;
}
return vec;
}
std::vector<int> func_b(std::vector<int> vec){
int j = 6;
for (auto& e : vec) {
e *= j++;
}
return vec;
}
std::vector<int> func_c(std::vector<int> vec){
//same as func_b
}
int main() {
std::vector<int> vec(10);
auto a=func_a(vec);
auto b=func_b(a);
auto c=func_c(b);
//or in one line
auto r = func_c(func_b(func_a(std::vector<int>(10))));
}
Or you can apply each function to the same vector:
void apply_func_a(std::vector<int>& vec){
int j = 1;
for (auto& e : vec) {
e = j++;
}
}
void apply_func_b(std::vector<int>& vec){
int j = 6;
for (auto& e : vec) {
e *= j++;
}
}
void apply_func_c(std::vector<int>& vec){
// same as apply_func_b
}
int main() {
std::vector<int> vec(10);
apply_func_a(vec);
apply_func_b(vec);
apply_func_c(vec);
}
I'm not a big fan of the third version (passing the input parameter as the output):
std::vector<int>& func_a(std::vector<int>& vec)
Most importantly, try to avoid C-style arrays and use std::vector or std::array, and don't use new, but std::make_unique and std::make_shared
I'm assuming you want to be able to modify a single array with no class-level attributes and without returning any pointers. Your above code can be modified to be a single function, but I've kept it as 3 to more closely match your code.
void func_a(int[] arr, int size){
for(int i = 0; i < size; i++)
arr[i] = i+1;
}
void func_b(int[] arr, int size){
int k = 6;
for(int i = 0; i < size; i++)
arr[i] *= (k+i);
}
//this function is exactly like func_b so it is really unnecessary
void func_c(int[] arr, int size){
int p = 6;
for(int i = 0; i < size; i++)
arr[i] *= (p+i);
}
But if you just want a single function:
void func(int[] arr, int size){
int j = 6;
for(int i = 0; i < size; i++)
arr[i] = (i+1) * (j+i) * (j+i);
}
This solution in other answers is better, if you are going to allocate memory then do it like this (and test it!) also if you are not using the default constructor and copy constructor then hide them, this will prevent calling them by accident
class A{
private:
A(const &A){}
A() {}//either define these or hide them as private
public:
int * a, *b, *c;
int size;
A(int sz) {
size = sz;
a = new int[size];
b = new int[size];
c = new int[size];
}
~A()
{
delete[]a;
delete[]b;
delete[]c;
}
//...
};

Initializing an Array C++

My code is trying to implement the union-find algorithm and I have the id[] array and the sz[] array. I initialize them in the Union-Find constructor, but once I try to use those arrays in the methods within the Union-Find class, it changes all the array values to 1. I don't understand why. Is there something obvious that I'm missing??
H File
class UnionFind{
public:
UnionFind(int size);
void join(int x, int y);
int connected(int x, int y);
int find(int x);
private:
int size;
int id[];
int sz[];
};
CPP File
UnionFind::UnionFind(int size){
this->id[size] = id[size];
for(int i = 0; i < size; i++){
id[i] = i;
}
for(int i = 0; i < size; i++){
sz[i] = 1;
}
}
int UnionFind::find(int l){
//Path Compression Finding the Root
for(int i = 0; i < 5; i++){
}
while(l != id[l]){
id[l] = id[id[l]];
l = id[l];
}
return l;
}
void UnionFind::join(int x, int y){
int m = find(x);
int n = find(y);
if(sz[m] < sz[n]){
id[m] = n;
sz[n] += sz[m];
}
else{
id[n] = m;
sz[m] += sz[n];
}
}
int UnionFind::connected(int x, int y){
if(find(x) == find(y)){
return 1;
}
else{
return 0;
}
}
From the comments.
you can't have int id[] as a class member,
use std::vector (resize and fill in constructor),
your forgot to set member size in constructor,
your find algorithm uses path halving not path compression (this does not affect the running time).
Side note: you can use a single array/vector to implement your disjoint set data structure.

Use function from another class or struct in a function within this class

I am creating a hash table and need to have this chained hash table tested with different hash functions.
I have hash structs such as
struct Hasher {
virtual int hash(std::string s, int N) = 0;
};
struct SumHasher : Hasher {
int hash(std::string s, int N){
int result = 0;
for (int i=0; i<s.size(); ++i)
result += s[i];
return int (std::abs((int)result)) % N;
}
};
struct ProdHasher : Hasher {
int hash(std::string s, int N) {
int result = 1;
for (int i=0; i<s.size(); ++i)
result *= s[i];
return int (std::abs((int)result)) % N;
}
};
struct ShiftHasher : Hasher {
int hash(std::string s, int N){
const int shift = 6; unsigned z = 0;
const int mask = ~z >> (32-shift); // lower 6 bits on
int result = 0;
for (int i = 0; i < s.length(); i++)
result = (result << shift) | (s[i] & mask);
return int (std::abs((int)result)) % N;
}
};
Now how can I use this functions within the Hashtable class by creating a struct hash type then passing that object to the constructor
class ChainedHashTable
{
ListNode **T; // array of linked lists
int capacity;
public:
Hasher *myhash;
int info;
ChainedHashTable(int numberOfChains, Hasher *myHasher){
myhash = hasher;
capacity = numberOfChains;
T = new ListNode* [capacity];
for (int i=0; i<capacity; ++i)
T[i] = NULL;
}
.......
void ChainedHashTable::insert(std::string key, int info){
int h = myhash::hash(key, capacity);
T[h] = ListNode::make(key, info, T[h]);
}
you should use:
myhash->hash(key, capacity)