Here is the deal. We have 2 different classes Class F and Class O
class F {
private:
int x;
int y;
public:
int getXf(){ return x; }
int getYf(){ return y; }
f(int ,int);
};
class O {
private:
int n;
int k;
int x;
int y;
char type;
int id;
int t;
public:
O(int ,int ,int ,int ,int);
int getX(){ return x; }
int getY(){ return y; }
};
And we have a third class P, where we initialize the values. In the class we are creating the two arrays of objects.
class Prog {
public:
int count;
int fcount;
O *o[]; //here we are declaring the arrays of objects
F *f[];
public :
//void init(); Here is the function where we initializing the values
};
Now the 2 for statements where we are creating the objects.
for(int i=0;i<10;i++){
randx = rand() % 10;
randy = rand() % 20;
o[i] = new O(100,50,i,randx,randy);
}
for(int i=0;i<3;i++){
randx = rand() % 10;
randy = rand() % 10;
f[i] = new F(randx, randy);
}
When we are printing all of the objects are here but the first 3 of the first class are replaced by the objects of the seconds. Exactly the 100 and 50 (1st for) from randx and randy (2nd for) respectively.
O *o[];
This declares an array of unknown size, which is an incomplete type. C++ doesn't allow that to be used as a class member, although some compilers will allow it as an extension, interpreting it as an array of zero size. In either case, it's not what you want.
If you know the array bound at compile time, then you should specify it:
O *o[10];
otherwise, you'll need to dynamically allocate an array at run time:
std::vector<O*> o;
for(int i=0;i<10;i++){
randx = rand() % 10;
randy = rand() % 20;
o.push_back(new O(100,50,i,randx,randy));
}
I would also suggest storing objects, or possibly smart pointers, rather than raw pointers in the array. If you really do want raw pointers for some reason, then remember to delete the objects once you've finished with them since that won't happen automatically, and don't forget the Rule of Three.
You are declaring arrays, but you never allocate memory for them. What you are seeing is just how your code is walking all over the stack.
Something more appropriate:
struct X {}; struct Y {};
class P {
public:
P() : xs(new X*[10]), ys(new Y*[10]) { init(); }
~P() {
// delete all objects
for(std::size_t i = 0; i < 10; ++i)
delete xs[i];
for(std::size_t i = 0; i < 10; ++i)
delete ys[i];
delete[] xs;
delete[] ys;
}
private:
void init() {
// initialize
for(std::size_t i = 0; i < 10; ++i)
xs[i] = new X();
for(std::size_t i = 0; i < 10; ++i)
ys[i] = new Y();
}
// prevent assignment and copy
P& operator=(const P& other);
P(const P&);
X** xs;
Y** ys;
};
Of course, all this magic becomes unnecessary if you just use
std::vector to store your data.
The problem is due to the way you declare your arrays:
O *o[/*No size here*/];
F *f[/*No size here*/];
Since you do not state the size of the arrays, this is equivalent to
O **o;
F **f;
Hence, you are declaring two members of types "pointer to pointer to O" and "pointer to pointer to F" respectively, but these are uninitialized and you have not allocated any memory for them to point to. That is, you actually don't have any arrays, just pointers which could be used to refer to the type of array you want.
If you know at compile time what size you want to use, you should specify that size in the declaration, which will give you a properly allocated array of that size. Otherwise, consider using an std::vector.
Related
I want to pass 2-dimensional arrays with different sizes to my class and store the arrays as private member variables.
When I try to declare the array in the constructor I get an error.
How should I declare a private variable from constructor?
If it is not possible, what else can I do to make my class flexible for different array sizes?
Here is the header file:
#ifndef NUMCPP_H
#define NUMCPP_H
class numcpp
{
public:
numcpp(int *Arr,int *Shape,int Dims);
private:
int *shape;
int dims;
};
#endif
Here is the source file:
#include <iostream>
#include "numcpp.h"
using namespace std;
numcpp::numcpp(int *Arr,int *Shape,int Dims) // *arr points to input array's first element
{
shape = Shape;
dims = Dims;
int i = shape[0];
int j = shape[1];
int numcpp::array[i][j]; // error happens in this line
//assigning input array to our variable
for (int x = 0; x < i; x++)
{
for (int y = 0; y < j; y++)
{
array[x][y] = *(arr + (x * i) + y);
};
};
};
Classes must have a compile time fixed size, so a true flexible array member isn't possible. The best you could do is either:
Templating the class on the array dimensions (compile time chosen fixed size)
Using a dynamically resizable type like std::vector<std::vector<int>> to get something functionally similar (runtime dynamically chosen size); the class itself remains fixed size, with the vector storing the dynamically allocated arrays on the free store (heap).
One implementation approach would look something like this (adding a declaration of std::vector<std::vector<int>> array; in the private section of the class declaration):
// Use initializers to initialize directly instead of default initializing, then replacing
numcpp::numcpp(int *arr,int *Shape,int Dims) : shape(Shape), dims(Dims), array(shape[0], std::vector<int>(shape[1]))
{
int i = shape[0];
int j = shape[1];
for (int c = 0; c < i * j; ++c) {
array[c / j][c % j] = arr[c];
}
};
I got stuck with deleting an dynamically allocated array of int.
I've got a destructor, where I'm trying to use a loop for to delete all elements of array and finally delete it.
I have code on http://rextester.com/OTPPRQ8349
Thanks!
class MyClass
{
public:
int _a;
int* c;
int fRozmiar;
static int fIlosc;
MyClass() //default constructor
{
_a=0;
c = new int [9];
for(int i = 0; i<=9; i++)
{
c[i] = 1;
}
fIlosc++;
}
MyClass(int a1, int c1) // parametrized constructor
{
_a=a1;
c = new int [c1];
for(int i = 0; i<=c1; i++)
{
c[i] = rand();
}
fIlosc++;
}
MyClass(const MyClass &p2) // copy constructor
{
_a =p2._a;
c = p2.c;
fRozmiar = p2.fRozmiar;
fIlosc = fIlosc;
fIlosc++;
}
~MyClass(); // destructor
static int getCount() {
return fIlosc;
}
};
//Initialize static member of class
int MyClass::fIlosc = 0;
MyClass::~MyClass()
{
for(int i = 0; i<sizeof(c); ++i)
{
delete[] c[i];
}
delete[] c;
fIlosc--;
}
int main()
{
}
Remove the for-loop, but keep the delete[] c after it.
Each int doesn't need to be deleted because they're not dynamically allocated. If you needed to delete them, then the for-loop wouldn't work becuase: sizeof(c) is not the size of the array, and delete[] should have been delete instead.
There are several problems in the code.
First, that loop in the destructor must go. If you didn’t new it, don’t delete it.
Second, a loop through an array of N elements should be for (int i = 0; i < N; ++i). Note that the test is i < N, not i <= N. The loops as currently written go off the end of the array. That’s not good.
Third, the copy constructor copies the pointer. When the first object goes out of scope its destructor deletes the array; when the copy goes out of scope its destructor also deletes the array. Again, not good. The copy constructor has to make a copy of the array. In order to do that the class needs to also store the number of elements the array.
Background: I'm stuck to arm-arago-linux-gnueabi-g++ (GCC) 4.3.3. Although answers that requires C++11 or later is also appreciated, please explicitly express any language requirement later than C++03.
The object's constructor fills values into tables to be used by the algorithm.
As those table does not change and are not supposed to be changed, I want the them to be const, how do I do that?
Difficulty #1, the values are computationally generated, and I don't want to hard code them in a source file.
Difficulty #2, the computing sometimes depends on inputs that are only available at runtime.
Difficulty #3, I don't know why but I don't want the array to be static, even though the values might be the same for all objects(cases where the values does not depend on runtime input).
Difficulty #4, it's an array, so initializer list in C++03 won't work.
Edit1:
A few weeks after this post, I found both std::array and std::vector are very good alternative to C-style array when std::array is not available.
You can encapsulate the tables in a private type, with a single const instance of that type in your object, then forward the relevant constructor parameters to the private object; this works because even a const object is non-const during its construction.
For example:
class MyClass {
const struct Tables {
double x[1000];
double y[200];
Tables(int i, double d) {
x[i] = d;
y[200 - i] = -d;
}
} tables;
public:
MyClass(int i, double d) : tables(i, d) {}
};
MyClass c(20, 5.5);
Another technique is to build the tables in an ephemeral mutable array whose lifetime is bounded by the lifetime of the constructor, then initialize the const array from those mutable arrays.
Using C++11 std::array (since array types can't be copy-initialized):
class MyClass {
static std::array<double, 1000> buildArray(...) {
std::array<double, 1000> array;
... // fill array
return array;
}
const std::array<double, 1000> mArray;
public:
MyClass(...) : mArray(buildArray(...)) {}
};
Note that std::array is easy to express in C++03; it doesn't depend on any C++11 language features.
If you're worried about the overhead of returning a large array, instrument it - even C++03 compilers are capable of optimising large array returns.
I think you could implement a class containing the actual non const array. That way you can easily compute the values in a constructor.
Then this class would only have to implement the operator[] to be usable as an array. Or it could also simply return a const reference to the array.
Implementation example :
#include <iostream>
using namespace std;
class const_array {
int *arr;
size_t size;
public:
const_array(size_t size, int typ): size(size) {
arr = new int[size];
size_t i;
int val = 0;
for (i=0; i<size; i++) {
val += typ;
arr[i] = val;
}
}
const_array(const const_array & src): size(src.size) {
arr = new int[size];
size_t i;
for (i=0; i<size; i++) {
arr[i] = src.arr[i];
}
}
~const_array() {
delete[] arr;
}
const int * const getArray() const {
return arr;
}
int getSize() const {
return size;
}
const int& operator[](int i) {
return arr[i];
}
};
int main() {
const_array a(16, 4);
// int *arr = a.getArray(); error
const int *arr = a.getArray();
int j = a[2];
int k = arr[2];
// int * pj = &(a[2]); error
const int * pj = &(a[2]);
const int * pk = &(arr[2]);
cout << "a[2]=" << j << " (" << pj << ") - a.getArray[2]="
<< j << " (" << pj << ")" << endl;
return 0;
}
I need to pass an array of pointers to a function,
In the example below, there is a class called base and an array of pointers called pool.
How can I pass the array pool to a function called function?
1) in case that I want to be able to change the original array of pointers.
2) in case that I only want to pass a copy of the array of pointers.
Thanks,
class base
{
};
void function (base * pool)
{
}
int main
{
base *pool[40];
function (pool[0]);
return 0;
}
class base
{
public:
int a;
};
void function (base ** pool)
{
for (int i = 0 ; i < 40; ++i)
cout<<pool[i]->a<<' ';
}
int main()
{
base *pool[40];
// Allocate 40 base objects and the 40 base pointers
// point to them respectively
for(int i = 0; i < 40; ++i)
{
pool[i] = new base;
pool[i]->a = i;
}
function (pool);
// free the 40 objects
for(int i = 0; i < 40; ++i)
delete pool[i];
return 0;
}
I added the a member just as an example.
Even better would be
void function (base ** pool, int n)
{
for (int i = 0 ; i < n; ++i)
cout<<pool[i]->a<<' ';
}
and
function (pool, n);
It's not so easy to pass a copy of the array - especially in the case where the objects itself are dynamically allocated.
To pass an array to a function, and maintain the type information about the array, you can use a template:
template <unsigned N>
void function (base *(&pool)[N]) {
}
There is no way to pass a copy of an array, unless it is inside a struct or class. In C++11, you have such a class in STL, called array:
#include <array>
template <unsigned N>
void function (std::array<base *, N> pool) {
pool[0] = 0;
}
base b;
std::array<base *, 40> p;
p[0] = &b;
function(p);
assert(p[0] == &b);
I'm trying to create my own version of an array called a safearray, to test my knowledge of operator overloading and creating proper class's and such.
I'm encountering two errors.
SafeArray.h:11:15: error: ‘const int SafeArray::operator’ cannot be overloaded
SafeArray.h:10:10: error: with ‘int& SafeArray::operator’
My code is split between three files.
Main.cpp
#include <cstdlib>
#include <iostream>
#include "SafeArray.h"
using namespace std;
int main(int argc, char** argv) {
SafeArray a(10); // 10 integer elements
for (int i = 0; i < a.length(); i++) {
cout << i << " " << a[i] << "s" << endl; // values initialise to 0
}
cout << endl << a[1]; // Program exits here.
a[3] = 42;
cout << a[3];
a[10] = 10;
cout << a[10];
a[-1] = -1; // out-of-bounds is "safe"?
SafeArray b(20); // another array
b = a; // array assignment
for (int i = 0; i < b.length(); i++) {
cout << b[i] << endl; // values copied from a
}
return 0;
}
SafeArray.h
#ifndef SAFEARRAY_H
#define SAFEARRAY_H
class SafeArray {
public:
SafeArray(int); // int variable will be the array size
int length();
int boundsCheck(int y); // constructor will call this function
// const SafeArray operator= (const SafeArray&);
int& operator[] (int y);
const int operator [] (const int y); // you need this one too.
SafeArray &operator=(SafeArray rhs) {
std::swap(array, rhs.array);
std::swap(length_, rhs.length_);
}
SafeArray(SafeArray const &other);
~SafeArray();
private:
int length_;
int *array;
//int array[];
};
#endif /* SAFEARRAY_H */
SafeArray.cpp
#include "SafeArray.h"
#include <iostream>
SafeArray::SafeArray(int x) {
length_ = x;
array = new int[length];
for (int i = 0; i < length_; i++) {
array[i] = 0;
}
}
int SafeArray::length() {
return this->length_;
}
int SafeArray::boundsCheck(int y) {
}
int& SafeArray::operator[] (int y) {
return array[y];
}
SafeArray::~SafeArray() {
delete [] array;
}
SafeArray::SafeArray(SafeArray const &other) {
int *temp = new int[rhs.size_];
for (int i=0; i<rhs.size_; i++)
temp[i] = rhs.array[i];
std::swap(temp, array);
delete [] temp;
return *this;
}
Your class definition isn't valid. int array[] is an incomplete type, which must not appear as a (non-static) class member. Some compilers accept this as a synonym for int array[0], but zero-sized arrays are not valid in C++, either (only in C99).
In short, you cannot write your code the way you do. You need to learn about dynamic allocation and manage your own memory. Check out how std::vector is implemented.
In C++11, I might recommend a std::unique_ptr<int[]> array as a quick-fix approach, to be initialized as array(new int[x]).
Actually int array[] is valid, and may appear as a class member. The following compiles with strict C++11 conformance:
class foo
{
public:
foo() {}
int length;
int A[];
};
void ralph()
{
foo *bar = (foo *)new int[ 21 ];
bar->length = 20;
bar->A[0] = 1;
}
This is legal, and has its advantages (occasionally). Although it is not commonly used.
However, I suspect that the OP wanted something more along the lines of
class SafeArray {
public:
SafeArray(int); // int variable will be the array size
int length();
int boundsCheck(int y); // constructor will call this function
int& operator[] (int y);
const int operator [] (const int y) // you need this one too.
private:
int length_;
int *array;
};
along with
SafeArray::SafeArray(int x) {
length_ = x;
array = new int[length];
for (int i = 0; i < length_; i++) {
array[i] = 0;
}
}
As #Kerrek already pointed out, your class definition is clearly wrong (shouldn't compile).
To fix it, you want to change the definition to something like:
int *array;
Then in your default ctor you could use something like this:
SafeArray::SafeArray(unsigned size = 0)
: array(new int[size])
{
for (unsigned i=0; i<size; i++)
array[i] = 0;
}
Then, yes, you'll need to write an assignment operator. The usual way is called the copy and swap idiom. You create a copy, then swap the contents of the current one with those of the copy:
SafeArray &operator=(SafeArray rhs) {
std::swap(array, rhs.array);
std::swap(length_, rhs.length_);
}
Along with that, you'll need a copy constructor that makes a copy of the data as well:
SafeArray::SafeArray(SafeArray const &other) {
int *temp = new int[rhs.size_];
for (int i=0; i<rhs.size_; i++)
temp[i] = rhs.array[i];
std::swap(temp, array);
delete [] temp;
return *this;
}
Finally, you'll need a destructor to destroy an object and (particularly) delete the memory it holds:
SafeArray::~SafeArray() {
delete [] array;
}
Then realize that all of that is an ugly mess that will never really work well. In particular, the basic methodology is restricted to an array that's basically fixed in size. As long as you only store ints, it's fairly easy to overlook the problems, and make a dynamic array that (sort of) works. When/if you want to store some other type, however, you just about need to separate allocating memory from initializing objects in that memory, which means throwing away essentially all the code above, and replacing it with something that:
keeps track of the array size and allocation size separately
allocates memory with ::operator new, an Allocator object, or something else similar
uses placement new to initialize objects in the memory when needed.
uses explicit destructor calls to destroy the objects
uses ::operator delete to release memory
and so on. To summarize, std::vector is not a trivial piece of work.
The error message refers to these two lines:
int& operator[] (int y);
const int operator [] (const int y); // you need this one too.
Your error message says that (int y) and (const int y) are too similar to be two different overloads of the [] operator. You cannot overload on (int y) and (const int y) because the calls would all be ambiguous.
You probably meant to return a const int if your SafeArray is const, but return an int& if your SafeArray is not const. In that case, you declare the second function to apply to const SafeArray, by putting the word const after the parameter list. This is what you should write in SafeArray.h:
int& operator[] (int y);
const int operator [] (int y) const; // you need this one too.
You would then have to write both of these functions in SafeArray.cpp:
int& SafeArray::operator[] (int y) {
return array[y];
}
const int SafeArray::operator[] (int y) const { // you need this one too.
return array[y];
}