copying an array of int* - c++

I have to create a copy constructor for my object, which look like this;
class DTable {
private:
std::string s_name;
int* *array;
int size;
public:
DTable();
DTable(std::string sName);
DTable(DTable &pcOther);
~DTable();
void vSetName(std::string sName);
std::string info();
int getValue(int index, bool &ok);
bool setValue(int index, int val);
const int defaultArrSize = 10;
const std::string defaultArrName = "Default Name";
};
Where array variable points at array of int*. Copy constructor i came up with looks like this;
DTable::DTable(DTable & pcOther) {
s_name = pcOther.s_name + "_copy";
size = pcOther.size;
array = new int*[size];
for (int i = 0; i < size; i++) {
array[i] = new int;
*array[i] = pcOther.*array[i];
}
}
The problem is that, i just cannot copy values of pointed int array to another array. Solution like this leaves me with error
expression must have pointer to member type
Also,
array[i] = pcOther.array[i];
is wrong, because that just copies references, so after altering one object, copy of it will be altered too. I want to avoid that.
I'd love to use different structure for this, but it has to be dynamically allocated array of int*

You can use the memcpy(),
void * memcpy ( void * destination, const void * source, size_t num );
or
*array[i] = *(pcOther.array[i])
for e.g.
DTable::DTable(DTable & pcOther) {
s_name = pcOther.s_name + "_copy";
size = pcOther.size;
array = new int*[size];
for (int i = 0; i < size; i++) {
array[i] = new int;
*array[i] = *(pcOther.array[i]);
// or
memcpy ( array[i], pcOther.array[i] , sizeof(int)*1 );
}
}

Related

what is this dynamic object creation * []

What does this mean? The following is a snippet from
here
class HashTableEntry {
public:
int k;
int v;
HashTableEntry(int k, int v) {
this->k= k;
this->v = v;
}
};
class HashMapTable {
private:
HashTableEntry **t;
public:
HashMapTable() {
t = new HashTableEntry * [T_S]; //What does this do
for (int i = 0; i< T_S; i++) {
t[i] = NULL;
}
}
In this code, t is a double pointer and it is assigned to new HashTableEntry * [T_S]
Does new HashTableEntry * [T_S] mean the Object HashTableEntry is being made into a pointer to point to an array with size of T_S?
If it is, I am not understanding how a dynamically created object with the new HashTableEntry is being delcared as an [T_S] when the definition of HashTableEntry is clearly a class/struct
t = new HashTableEntry * [T_S]
This creates an array of pointers to HashTableEntry. It creates T_S counts of them.
Perhaps it is clearer if written like this:
using HTEntry = HashTableEntry*;
t = new HTEntry [T_S];

C++ deprecated conversion from string constant to 'char*' []

Whenever I try to run my code I get these error lines. It also seems like that sometimes it crashes the program. Is that possible or something else causes the crash?
The error code comes to these lines:
Buffer<char*> s(20,"s.txt","rw"); //20 long char*
for(unsigned int i=0;i<24;i++){ //it overwrites the size of s after default 20
s[i]="hey"; //error here: "deprecated conversion from string constant to 'char*'"
The class looks like this(deleted the unimportant parts":
template<class T>
class Buffer:public File_ptr
{
unsigned int siz;
T *data;
public:
///constructor(size,filename,openmode)
Buffer(unsigned int s,const char* n, const char* m):File_ptr(n,m),siz(s)
{
data= new T[siz];
/* for(unsigned int i=0; i<siz; ++i)
{
data[i]=0;
}; */
};
///destructor
~Buffer()
{
delete[] data;
}
///operator[]
T& operator[](unsigned int i)
{
if(i>siz-1)
{
unsigned int newsize=siz*2;
T* tmp=new T[newsize];
for(unsigned int j = 0; j < siz; j++)
{
tmp[j] = data[j];
}
siz=newsize;
delete[] data;
data=tmp;
};
return data[i];
};
Any idea why I get the error?
Thanks in advance!
"hey" is a string literal and so the compiler stores it in a different part of the executable which is likely to be stored in write-protected memory along with all other strings. As a result, in C++, in a pointer context it evaluates to const char*.
The solution is to declare
Buffer<const char*> s(20,"s.txt","rw");
template<class T>
class Buffer
{
unsigned int siz;
T *data;
public:
///constructor(size,filename,openmode)
Buffer(unsigned int s,const char* n, const char* m):siz(s)
{
data= new T[siz];
}
///destructor
~Buffer()
{
delete[] data;
}
///operator[]
T& operator[](unsigned int i)
{
if(i>siz-1)
{
unsigned int newsize=siz*2;
T* tmp=new T[newsize];
for(unsigned int j = 0; j < siz; j++)
{
tmp[j] = data[j];
}
siz=newsize;
delete[] data;
data=tmp;
}
return data[i];
}
};
int main() {
Buffer<char*> s(20,"s.txt","rw"); //20 long char*
for(unsigned int i=0;i<24;i++){ //it overwrites the size of s after default 20
s[i]="hey";
}
}
Live demo: http://ideone.com/Dgdcui
You're attempting to store a string literal in a char* variable - indicating that it is writable.
A string literal will typically be stored in the read only data segment of your application binary (See this question)
From the C++ FAQ
...it turns into an unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified
Attempting to write to a memory location in the read-only data segment will cause your program to terminate - hence the crash.

Segmentation fault when creating a row-major array

I'm trying to implement a row-major array, which is basically a single dimension representation of a 2D array.
This is my class definition
class RMA{
public:
RMA(){
size_=0;
row_=0;
column_=0;
arr_ = new double[size_];
}
RMA(int n, int m){
size_ = n*m;
column_ = m;
row_ = n;
if(size_== 0) arr_ = 0;
else arr_ = new double[size_];
}
RMA(const RMA& arr) {
size_ = arr.size_;
if(this != &arr){
delete [] arr_;
arr_ = new double[size_];
for(int i=0; i<size_; i++){
arr_[i] = arr.arr_[i];
}
}
return *this;
}
const double& operator() (int n, int m) const{
return arr_[n*column_+m];
}
double& operator()(int n, int m){
return arr_[n*column_+m];
}
~RMA(){delete[] arr_ ;}
private:
int size_;
int column_;
int row_;
double* arr_;
}
I've a calling function which creates the array.
RMA create_array() {
RMA arr;
arr = RMA(N, M);
std::cout<<"success";
return arr;
}
And this is my client
int main(int argc, char* argv[]) {
RMA arr = create_array();
return 0;
}
I end up getting segmentation fault. What am I doing wrong.
You use operations, that instead of cloning array, take a shallow copy of an object, and when destructors are used, they try to release the same memory block.
Implement the following operations:
RMA::RMA(const RMA&); // copy constructor - clone buffer
RMA& operator=(const &RMA); // assignment - clone buffer, release old
Also instead of:
RMA rma;
rma = RMA(a,b);
Use:
RMA rma = RMA(a,b) or RMA rma(a,b);
Edit: constructor code:
RMA::RMA(const RMA &rma) : size_(0), row_(0), column_(0), buffer_(0)
{
*this = rma;
}
RMA &operator=(const RMA&rma)
{
double *old = buffer_;
size_ = rma.size_;
row_ = rma.row_;
column_ = rma.column_;
buffer_ = new double[size_];
memcpy(buffer_, rma.buffer_, sizeof(buffer_[0]) * size_);
delete []old;
return *this;
}
The best solution is to get rid of all the new/delete, copy-constructors, and fluff. Use a private member variable to manage the memory, and follow the Rule of Zero. Like this:
struct RMA
{
RMA(size_t r = 0, size_t c = 0)
: row(r), column(c), arr(r * c) {}
const double& operator() (int n, int m) const
{ return arr[n * column + m]; }
double& operator() (int n, int m)
{ return arr[n * column + m]; }
private:
std::vector<double> arr;
size_t row, column;
};
That's it. You should not write any copy-constructor, assignment operator, move whatever, because the default-generated ones already do the right thing.
NB. row is actually redundant in my example too, you could remove it and calculate it when needed as arr.size() / column.
You could use .at( ) instead of [ ] on vector in order to throw an exception for out-of-bounds access, instead of causing undefined behaviour.

C/C++, troubles with pointers and functions

I have a little question about understand how pointers and functions work.
I want to see how a function looks like qsort(), but I need to use my own function to swap elements and to compare elements. I am very surprised to know that my function does not swap data...
My code:
//prototypes file: other.h
void Sort(char* pcFirst, int nNumber, int size, void (*Swap)(void*, void*), int (*Compare)(void*, void*) ); //sorts any arrays
void SwapInt(void* p1, void* p2); // swap pointers
int CmpInt(void* p1, void* p2); // compare poineters
//realisation file: other.cpp
#include "other.h"
void Sort(char* pcFirst, int nNumber, int size,
void (*Swap)(void*, void*), int (*Compare)(void*, void*) )
{
int i;
for( i = 1; i < nNumber; i++)
for(int j = nNumber - 1; j >= i; j--)
{
char* pCurrent = pcFirst + j * size;
char* pPrevious = pcFirst + (j - 1) * size;
if( (*Compare)( pPrevious, pCurrent ) > 0 )// if > 0 then Swap
{
(*Swap)( pPrevious, pCurrent );
}
}
}
void SwapInt(void* p1, void* p2)
{
int * ptmp1 = static_cast<int*>(p1);
int * ptmp2 = static_cast<int*>(p2);
int * ptmp = ptmp1;
ptmp1 = ptmp2;
ptmp2 = ptmp;
}
int CmpInt(void* p1, void* p2)
{
int nResult;
int * ptmp1 = static_cast<int*>(p1);
int * ptmp2 = static_cast<int*>(p2);
nResult = (*ptmp1 - *ptmp2);
return nResult;
}
//main file: lab.cpp
#include <tchar.h>
#include <iostream>
#include <cstdio>
#include <cmath>
#include "other.h"
int _tmain()
{
int nAr[] = {33,44,55,22,11}; //array for sort
int nTotal = sizeof(nAr) / sizeof(int); //number of elements
for ( int i = 0; i < nTotal; i++)
{
printf("%d ",nAr[i]); // result of cycle is 33 44 55 22 11
}
Sort(reinterpret_cast<char*>(&nAr[0]), nTotal, sizeof(int), SwapInt, CmpInt);
for ( int i = 0; i < nTotal; i++)
{
printf("%d ",nAr[i]); // result of cycle is 33 44 55 22 11 too =(
}
}
Why does the array not change?
In the debugger I can see that all pointers change, and get correct values, but in main my array is not changed.
pointers point to objects
the code
int * ptmp = ptmp1;
ptmp1 = ptmp2;
ptmp2 = ptmp;
changes some pointer values locally in the function, and that's all.
in order to swap the values of two objects, pass them by reference:
void swap_values_of( int& a, int& b )
{
int const original_a = a;
a = b;
b = original_a;
}
you can also do that, less safely, with pointer arguments, then taking care to swap the values pointed to instead of the pointers themselves.
but except for purposes of learning, use std::swap instead
not asked for, but... if you change the current Microsoft-specific
int _tmain()
to just standard
int main()
then the code will (much more likely) work also in e.g. Linux.
just a tip
You may look at various combinations as these.....
#include<iostream>
#include<stdio.h>
#include<malloc.h>
//Call by Address
void SwapIntAddr(int* ptmp1, int* ptmp2)
{
int ptmp;
ptmp = *ptmp1;
*ptmp1 = *ptmp2;
*ptmp2 = ptmp;
}
//Call by Reference
void SwapIntRef(int& ptmp1, int& ptmp2)
{
int ptmp;
ptmp = ptmp1;
ptmp1 = ptmp2;
ptmp2 = ptmp;
}
//Call by Reference but in pointer level
void SwapPtrRef(int*& ptmp1, int*& ptmp2)
{
int* ptmp;
ptmp = ptmp1;
ptmp1 = ptmp2;
ptmp2 = ptmp;
}
//Call by Address but in Pointer level.
void SwapPtrAddr(int** ptmp1,int** ptmp2)
{
int** ptmp = (int**) malloc(sizeof(int*));
*ptmp = *ptmp1;
*ptmp1 = *ptmp2;
*ptmp2 = *ptmp;
}
int main(){
int a = 3, b= 5;
int* p1 = &a;
int* p2 = &b;
SwapIntAddr(p1,p2);
printf("%d %d\n",*p1,*p2);
SwapIntRef(*p1,*p2);
printf("%d %d\n",*p1,*p2);
SwapPtrRef(p1,p2);
printf("%d %d\n",*p1,*p2);
SwapPtrAddr(&p1,&p2);
printf("%d %d\n",*p1,*p2);
return 0;
}
Your SwapInt function swaps some pointers, not ints. Since all those pointers are local to SwapInt, it has no actual effect. Probably you meant to do something with the ints *ptmp1 and *ptmp2.
What you are actually doing is swapping pointers. What you are trying to do is to swap values, where that pointers point to. At least that comes from your program logic.
So your code could be something like this:
void SwapInt(void* p1, void* p2)
{
int * ptmp1 = static_cast<int*>(p1);
int * ptmp2 = static_cast<int*>(p2);
int ptmp = *ptmp1;
*ptmp1 = *ptmp2;
*ptmp2 = ptmp;
}

dynamic array member variables

Hey i'm new to c++ and still working out its perticularities. I'm having the darnedest time trying to figure out whats going wrong with this code. I've stepped through it and everything is calculating correctly. The issue is that value_array in the base class doesn't seem to be retaining the values once the derived class Calculate function ends. I think i've declared and allocated the array properly. I'm stumped...
#include <iostream>
class Indicator
{
protected:
double * value_array;
double * input_array;
int input_size;
public:
Indicator(double input[], int size)
{
input_array = input;
input_size = size;
value_array = new double[size]; // issue with value_array
}
double operator[] (int index) { return value_array[index]; }
void virtual Calculate() {}
~Indicator() { delete[] value_array; }
};
class SMA : public Indicator
{
private:
int nperiod;
double sum;
public:
SMA(double input[], int size, int period) : Indicator(input, size)
{
nperiod = period;
sum = 0;
Calculate();
}
void Calculate();
};
void SMA::Calculate()
{
for (int i=0; i<input_size; i++)
{
if (i > nperiod - 1)
{
sum += input_array[i] - input_array[i-nperiod];
value_array[i] = sum / nperiod;
}
else
{
sum += input_array[i];
value_array[i] = sum / (i+1);
}
}
}
int main(int argc, const char *argv[]) {
double input[] = {1,2,3,4,5,6,7,8,9,10};
Indicator indicator = SMA(input,10,5);
double value = indicator[0];
std::cout << "value: " << value << std::endl;
std::cin.get();
exit(0);
}
Update:
Here is the code implemented with vectors. I wanted to leave the input as double[] to be consistent with other libraries, any other potential issues I should be aware of?
#include <iostream>
#include <vector>
class Indicator
{
protected:
std::vector<double> value_vector;
double * input_array;
int input_size;
public:
Indicator(double input[], int size)
{
input_array = input;
input_size = size;
value_vector.reserve(size);
}
double operator[] (int index) { return value_vector[index]; }
void virtual Calculate() {}
};
class SMA : public Indicator
{
private:
int nperiod;
double sum;
public:
SMA(double input[], int size, int period) : Indicator(input, size)
{
nperiod = period;
sum = 0;
Calculate();
}
void Calculate();
};
void SMA::Calculate()
{
for (int i=0; i<input_size; i++)
{
if (i > nperiod - 1)
{
sum += input_array[i] - input_array[i-nperiod];
value_vector.push_back(sum / nperiod);
}
else
{
sum += input_array[i];
value_vector.push_back(sum / (i+1));
}
std::cout << "sma: " << value_vector[i] << std::endl;
}
}
int main(int argc, const char *argv[]) {
double input[] = {1,2,3,4,5,6,7,8,9,10};
Indicator indicator = SMA(input,10,5);
for (int i=0; i<10; i++)
{
std::cout << "main: " << indicator[i] << std::endl;
}
std::cin.get();
exit(0);
}
That's because you're violating the Rule of Three. Since your class manages a resource, it needs a copy constructor and an assignment operator. I strongly suggest replacing any T* data member with a std::vector<T> data member. Then you don't need to write those special member functions manually.
Hia,
a few things are wrong.
As FredOverflow says you need a copy constructor and assignment, something like:
Indicator::Indicator(const Indicator& other)
{
input_size = other.input_size;
//direct copy of reference as indicator doesn't own this data
//Note a shared pointer (such as boost::shared_ptr) would be better than a naked reference
input_array = other.input_array;
//construct a new set of data
value_array = new double[input_size];
//do you want to copy the data too? maybe a memcpy follows?
memcpy(value_array, other.value_array, input_size*sizeof(double));
}
Then you need an assignment
Indicator&
Indicator::operator=(const Indicator& other)
{
//make sure you are not assigning itself
if(this != &other)
{
input_size = other.input_size;
//direct copy of reference as indicator doesn't own this data
//Note a shared pointer (such as boost::shared_ptr) would be better than a naked reference
input_array = other.input_array;
//destroy old data and construct a new set of data
delete[] value_array;
value_array = new double[input_size];
//do you want to copy the data too? maybe a memcpy follows?
memcpy(value_array, other.value_array, input_size*sizeof(double));
}
return *this;
}
You probably also want to make the destructor virtual - see here for why -
it helps prevent memory leaks in the destructor of SMA
virtual ~Indicator() { delete[] value_array; }
Use std::vector instead of raw arrays.
std::vector handles all the memory management and copying and so forth.
Cheers & hth.,