Reference to non-object array from class - c++

Let's say my function had array passed in it like this:
int someFunction ( SomeClass * const * array, int arr_size ) { }
This is array of some structures:
struct SomeStruct {
int value;
int value2;
};
What I'm trying to achieve is making a reference inside of object declared in that function:
int someFunction ( SomeStruct * const * array, int arr_size )
{
NewClass newclass (array, arr_size);
}
my constructor would look like this:
Newclass::NewClass( SomeStruct * const * array, int arr_size )
{
SomeStruct ** myReference = new SomeStruct * [arr_size];
for (int i = 0; i < arr_size; ++i)
{
myReference[i] = array[i];
}
myReference[0] -> value = 10;
}
Now, if I want to print out value of first element in array, I get just zero.
int someFunction ( SomeStruct * const * array, int arr_size )
{
NewClass newclass (array, arr_size);
cout << array[0] -> value << endl;
}
Output:
0
Is it even possible to refer to non-object from class? How do I get my reference array to change the source array? I had the reference array in that function as a non object before and everything worked fine. And no, I can't just leave it there.

When you're allocating the struct pointers in Newclass::NewClass(), you're forgetting to actually initialize those pointers to point to the actual structs.
You need:
Newclass::NewClass(SomeStruct* const* array, int arr_size)
{
SomeStruct** myReference = new SomeStruct*[arr_size];
for (int i = 0; i < arr_size; ++i) {
myReference[i] = array[i];
}
myReference[0]->value = 10;
}
Though I must say I'm confused about all the pointer indirection and why you need it. And you're leaking memory too; you never delete[] myReference.
And you should consider using std::vector instead of doing all that memory management manually.

Related

2d Array to a function expecting int** array as parameter

I want to use a function made for dynamic arrys for an pre-initialised array too.
int MinInRow(int** fieldArray, int value, int currentColumn, int maxNumColumns)
{
int minVal = 0;
for (int inkrCol = 0; inkrCol < maxNumColumns; inkrCol++)
{
if (feldArray[currentColumn][inkrSpalte] < value)
{
minVal = feldArray[currentColumn][inkrCol];
}
}
return minVal;
}
So if I try
int testArray[3][4] =
{ {4,5,6,7},
{0,1,2,3},
{9,8,10,11}, };
int (*bufferArray)[4] = testArray;
or...
int** bufferArray = testArray;
or...
...
int main()
{
/*
read in other needed parameters
....
*/
std::cout << MinInRow((*bufferArray)[4], int value, int currentColumn, int maxNumColumns);
retrun 0;
}
I cant compile. But shouldnt int** bufferArray = testarray; just work fine? I mean there is always an double pointer to the first address of an 2D-Array.
how can I hand it over to the MinInRow-function? Thanks!
There is a little problem. "*" That one tell you that you want to make a pointer, but a pointer doesn't want a variable, he want the address. And then you've written
int** bufferArray = testarray.
You should write
int* bufferArray = new int [size of array] It's for 1D array
and ....
int** bufferArray = new int* [rows];
for (size_t = 0 ; i != rows ; ++i){
bufferArray[i] = new int [colons];
}
for 2D array
"I cant compile. But shouldnt int** bufferArray = testarray; just work fine? I mean there is alway an double pointer to the first address of an 2D-Array."
And Yes, it will be work nice. If testarray already 2D array

How to reference a 2d pointer?

In my code I create a function outside of the main, which creates a 1D array and initializes to 0.
void create_grid(double *&y, int Npoints)
{
y = new double[Npoints];
for (int i = 0; i < Npoints; i++)
{
y[i] = 0;
}
}
If I didn't have the syntax of declaring in the function as double *&y I couldn't access the values of y.
I tried doing the same for a 2D array but i don't know the syntax. I tried &&**y and &*&*y but it didn't work. Does anyone know how to create a function outside of the main, which initializes a 2d dynamic array so I can use it in the main?
E.g.:
void create_grid_2D(double **&&y, int Npoints1, int Npoints2)
{
y = new double*[Npoints1];
for (int i = 0; i < Npoints1; i++)
{
y[i] = new double[Npoints2];
}
for (int i = 0; i < Npoints1; i++)
{
for (int j = 0; j < Npoints2; j++)
{
y[i][j] = 0;
}
}
}
int main()
{
int N = 10;
double **z;//correcting this line, i wrote z**
create_grid_2D(z, N, N);
delete[]z;
return 0;
}
C++ does not allow forming a pointer to reference or reference to reference. (And without a space between the characters, && is a single token meaning something entirely different.)
And your declaration double z**; is incorrect - you probably mean double **z;.
To write a function that takes the argument double **z by reference, you just want a reference to pointer to pointer:
void create_grid_2D(double **&y,int Npoints1,int Npoints2)
{
//...
}
Except don't use new and delete. Using them slightly wrong leads to memory leaks and bugs with dangling pointers and double deletes. For example, you tried to clean up your memory in main with delete []z;, but new-expressions were evaluated 11 times to your one delete-expression, so this misses out on deleting the row arrays z[0], z[1], ... z[9]. There's pretty much always a better and simpler way using std::unique_ptr, std::shared_ptr, std::vector, or other RAII (Resource Allocation Is Initialization) tools.
So I would change the function to:
void create_grid_2D(std::vector<std::vector<double>>& y,
unsigned int Npoints1,
unsigned int Npoints2)
{
y.assign(Npoints1, std::vector<double>(Npoints2, 0.0));
}
int main()
{
unsigned int N=10;
std::vector<std::vector<double>> z;
create_grid_2D(z, N, N);
// No manual cleanup necessary.
}
Or even use a return value rather than assigning an argument:
std::vector<std::vector<double>> create_grid_2D(
unsigned int Npoints1,
unsigned int Npoints2)
{
return std::vector<std::vector<double>>(
Npoints1, std::vector<double>(Npoints2, 0.0));
}
int main()
{
unsigned int N=10;
std::vector<std::vector<double>> z = create_grid_2D(N, N);
}
An easy trick to resolve/write such complicated references is (simplified version for the sake of this problem - it's a bit more complicated with braces present): start from the variable name and go to the left, step by step. In your case:
... y
y is ...
... & y
y is a reference ...
... *& y
y is a reference to a pointer ...
... **& y
y is a reference to a pointer to a pointer ...
double**& y
y is a reference to a pointer to a pointer to a double
So, the correct definition is:
void create_grid_2D(double**& y,int Npoints1,int Npoints2)
But as mentioned in the comments, please do really consider avoiding raw pointers in favor of std::vector and other standard containers.
So you want a reference on a pointer to a pointer.
2d pointer is int**, and the reference is int**&. That's what you want to use.
Then, you should a container or at least a smart pointer instead.
This approach would be a little different than what you currently have but basically you want a 2D grid and another name for this is simply a MxN Matrix! We can do this very easily with a simple template structure. This template class will hold all of the contents without having to put the data into dynamic memory directly. Then once you have your class object that you want to use we can then put that into dynamic memory with the use of smart pointers!
#include <iostream>
#include <memory>
template<class T, unsigned M, unsigned N>
class Matrix {
static const unsigned Row = M;
static const unsigned Col = N;
static const unsigned Size = Row * Col;
T data[Size] = {};
public:
Matrix() {};
Matrix( const T* dataIn ) {
fillMatrix( dataIn );
}
void fillMatrix( const T* dataIn );
void printMatrix() const;
};
template<class T, unsigned M, unsigned N>
void Matrix<T, M, N>::fillMatrix( const T* dataIn ) {
for ( unsigned i = 0; i < Size; i++ ) {
this->data[i] = dataIn[i];
}
}
template<class T, unsigned M, unsigned N>
void Matrix<T,M,N>::printMatrix() {
for ( unsigned i = 0; i < Row; i++ ) {
for ( unsigned j = 0; j < Col; j++ ) {
std::cout << this->data[i*Col + j] << " ";
}
std::cout << '\n';
}
}
int main() {
// our 1 day array of data
double data[6] = { 1,2,3,4,5,6 };
// create and print a MxN matrix - in memory still a 1 day array but represented as 2D array
Matrix<double,2,3> A;
A.fillMatrix( data );
A.printMatrix();
std::cout << '\n';
Matrix<double, 3,2> B( data );
B.printMatrix();
std::cout << '\n';
// Want this in dynamic memory? With shared_ptr the memory is handled for you
// and is cleaned up upon it's destruction. This helps to eliminate memory leaks
// and dangling pointers.
std::shared_ptr<Matrix<float,2,3>> pMatrix( new Matrix<float,2,3>( data ) );
pMatrix->printMatrix();
return 0;
}
Output:
1 2 3
4 5 6
1 2
3 4
5 6
1 2 3
4 5 6

second Constructor called in c++ ( wrong output)

I am trying to do a simple thing but suddenly stuck in between .
Here in my code I am trying to call a constructor in which i would only pass the length, my first constructor initializes an array of size = length with all elements 0.
Then i am passing the array to the constructor to give the previously defined array its values
here is the sample :
class myvector
{
int *arr;
int length;
public :
myvector(int);
myvector(int *);
};
myvector :: myvector (int len)
{
arr = new int [length = len];
for ( int i=0;i< length;i++)
{
arr[i] = 0;
}
}
myvector :: myvector ( int *ex)
{
for ( int i=0;i< length;i++)
{
cout << ex[i] << " " << length <<" ";
arr[i] = ex[i];
cout << arr[i]<< " ";
}
}
int main()
{
myvector v1(5);
int x[5] = {2,3,4,45,6};
v1 = x;
}
Here in my second constructor length which was defined in first constrcutor lost its values , also array arr loses its values
Did I do something ?
Please elaborate me on this
I don't think you quite get what the circumstances are in which constructors are invoked. The line v1 = x doesn't put the values into the memory allocated during the first constructor call. Rather, it constructs a new myvector (using the second constructor) and copies it into v1. The stuff you do during the first constructor call is lost.
It sounds like you want to define an assignment operator, not a constructor taking an int* argument. Also, in general you should declare single-argument constructors as explicit to prevent this sort of thing from happening accidentally.
First of all, when specifying a size of array like this, you should provide a constant value. See here. And I really encourage you to use std::vector<> for such tasks.
But anyway, like Sneftel mentioned, seems like you want to define an assignment operator (see here for more information about overloading operators in tasks like yours).
Here how I'd implemented it(NOT and ideal solution, but it works, and gives a basic idea):
#include <iostream>
using namespace std;
class myvector
{
int *arr;
int length;
public :
//I completely removed second constructor
myvector(int);
~myvector();
void operator=(const int* otherArray);
void printArray();
};
myvector::myvector (int len)
{
length = len;
arr = new int[length]; // This is the way, how you can handle a non constant array sizes
for ( int i=0;i< length;i++)
{
arr[i] = 0;
}
}
void myvector::printArray()
{
for(unsigned i = 0; i < length; ++i)
cout<<"arr["<<i<<"] = "<<arr[i]<<endl;
}
//Here's an overloaded '=' operator.
//int x[5] = {2,3,4,45,6};
//myvector v;
//v = x; - here this function is called
void myvector::operator=(const int* otherArray)
{
for(unsigned i = 0; i < length; ++i)
arr[i] = otherArray[i];
}
myvector::~myvector()
{
delete []arr; // You should ALWAYS delete what you allocated with new
}
int main()
{
myvector v1(5);
int x[5] = {2,3,4,45,6};
v1 = x;
v1.printArray();
}

Returning a dynamically created array from function

I'm trying to create a function that would dynamically allocate an array, sets the values of the elements, and returns the size of the array. The array variable is a pointer that is declared outside the function and passed as a parameter. Here is the code:
#include <cstdlib>
#include <iostream>
using namespace std;
int doArray(int *arr) {
int sz = 10;
arr = (int*) malloc(sizeof(int) * sz);
for (int i=0; i<sz; i++) {
arr[i] = i * 5;
}
return sz;
}
int main(int argc, char *argv[]) {
int *arr = NULL;
int size = doArray(arr);
for (int i=0; i<size; i++) {
cout << arr[i] << endl;
}
return 0;
}
For some reason, the program terminates on the first iteration of the for loop in main()! Am I doing something wrong?
If you want to allocate memory that way you have to use:
int doArray(int*& arr)
else the pointer will only be changed inside the function scope.
You're passing in the array pointer by value; this means that when your doArray function returns, the value in arr in main is still NULL - the assignment inside doArray doesn't change it.
If you want to change the value of arr (which is an int *), you need to pass in either a pointer or a reference to it; hence, your function signature will contain either (int *&arr) or (int **arr). If you pass it in as a ** you'll also have to change the syntax inside the function from using arr to *arr (pointer-dereferencing), and you'll call it like so: doArray(&arr).
Also, in C++ you should really be using new int[sz] instead of malloc.
You need to add an extra level of indirection to doArray. As written it allocates the array properly but it doesn't communicate the pointer value back to the caller correctly. The pointer from malloc is lost once you return.
If you wrote a function to take a float and change the value, passing the changed value back to the caller, it would need to take a pointer: foo(float *f). Similarly, here you want to pass back an int* value to the caller so your function must be declared as doArray(int **arr) with a second asterisk.
int doArray(int **arr) {
int sz = 10;
*arr = (int*) malloc(sizeof(int) * sz);
for (int i=0; i<sz; i++) {
(*arr)[i] = i * 5;
}
return sz;
}
int main(int argc, char *argv[]) {
int *arr = NULL;
int size = doArray(&arr);
for (int i=0; i<size; i++) {
cout << arr[i] << endl;
}
return 0;
}
Notice how it now dereferences *arr inside of doArray, and how the call is now written as doArray(&arr).
The arr variable in your function is a local copy of the arr pointer in the main function, and the original is not updated. You need to pass a pointer-to-pointer or pointer reference (the former will also work in plain c, the later only in c++).
int doArray(int **arr)
or
int doArray(int*& arr)
Change signature to (specific for c++):
int doArray(int *&arr)
so pointer would be changed at exit from doArray.
You need a pointer to a pointer in your doArray() parameter. If you've never done any programming with pointers before, this can be confusing. I find that it can be easier to see the right types if you annotate your code abundantly with typedefs.
You have the right idea that (int*) can be used to represent an array. But if you want to change the value of your variable arr in main(), you need a pointer to that, and so you will end up with (untested code) something like the following
typedef int *IntArray;
int doArray(IntArray *arr) {
int sz = 10;
*arr = (IntArray) malloc(sizeof(int) * sz);
IntArray theArray = *arr;
for (int i=0; i<sz; i++) {
theArray[i] = i * 5;
}
return sz;
}
when calling doArray, you will need to pass the address of your variable (so doArray knows where to write to):
int main(int argc, char *argv[]) {
int *arr = NULL;
int size = doArray(&arr);
for (int i=0; i<size; i++) {
cout << arr[i] << endl;
}
return 0;
}
This should work.
As others have pointed out, you're passing your array (the int *) by value, so when you say arr=... you're not actually changing the array you passed in.
You're also got a memory leak, as you've written it. It's not a big deal when you only call doArray once in the body of your program, but if it gets called repeatedly and the array is never freed (or deleted, if you made it with new) then it can cause problems. Typically the best way to deal with this is by using the STL. You'd then write
#include <vector>
#include <iostream>
int doArray(std::vector<int> &arr) {
int sz = 10;
arr.resize(sz);
for (int i=0; i<sz; i++) {
arr[i] = i * 5;
}
return sz;
}
int main(int argc, char *argv[]) {
std::vector<int> arr;
int size = doArray(arr);
for (int i=0; i<size; i++) {
std::cout << arr[i] << std::endl;
}
return 0;
}
However, with the STL there are more idomatic ways than returning the size, since you can just ask for arr.size(), and if you get really fancy, can use functions like for_each or the ostream_iterator to print all your elements.

How to allocate a 2D array of pointers in C++

I'm trying to make a pointer point to a 2D array of pointers. What is the syntax and how would I access elements?
By the letter of the law, here's how to do it:
// Create 2D array of pointers:
int*** array2d = new (int**)[rows];
for (int i = 0; i < rows; ++i) {
array2d[i] = new (int*)[cols];
}
// Null out the pointers contained in the array:
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
array2d[i][j] = NULL;
}
}
Be careful to delete the contained pointers, the row arrays, and the column array all separately and in the correct order.
However, more frequently in C++ you'd create a class that internally managed a 1D array of pointers and overload the function call operator to provide 2D indexing. That way you're really have a contiguous array of pointers, rather than an array of arrays of pointers.
It depends. It can be as simple as:
int main()
{
int* data[10][20]; // Fixed size known at compile time
data[2][3] = new int(4);
}
If you want dynamic sizes at runtime you need to do some work.
But Boost has you covered:
int main()
{
int x;
int y;
getWidthAndHeight(x,y);
// declare a 2D array of int*
boost::multi_array<int*,2> data(boost::extents[x][y]);
data[2][3] = new int(6);
}
If you are fine with jagged arrays that can grow dynamically:
int main()
{
std::vector<std::vector<int*> > data;
data.push_back(std::vector<int*>(10,NULL));
data[0][3] = new int(7);
}
Note: In all the above. I assume that the array does not own the pointer. Thus it has not been doing any management on the pointers it contains (though for brevity I have been using new int() in the examples). To do memory management correctly you need to do some more work.
int *pointerArray[X][Y];
int **ptrToPointerArray = pointerArray;
That's how you make a true (contiguous in memory) multidimensional array.
But realize that once you cast a multidimensional array to a pointer like that, you lose the ability to index it automatically. You would have to do the multidimensional part of the indexing manually:
int *pointerArray[8][6]; // declare array of pointers
int **ptrToPointerArray = &pointerArray[0][0]; // make a pointer to the array
int *foo = pointerArray[3][1]; // access one element in the array
int *bar = *(ptrToPointerArray + 3*8 + 1); // manually perform row-major indexing for 2d array
foo == bar; // true
int *baz = ptrToPointerArray[3][1]; // syntax error
double** array = new double*[rowCnt];
for (int row = 0; row < rowCnt; ++row)
array[row] = new double[colCnt];
for (int row = 0; row < rowCnt; ++row)
for (int col = 0; col < colCnt; ++col)
array[row][col] = 0;
You could try Boost::MultiArray.
Check out this page for details.
:)
I had these once in a piece of code I wrote.
I was the laughing stock of the team when the first bugs leaked out. On top of that we use Hungarian notation, leading to a name like papChannel - a pointer to an array of pointers...
It's not nice. It's nicer to use typedefs to define a 'row of columns' or vice versa. Makes indexing more clear, too.
typedef int Cell;
typedef Cell Row[30];
typedef Row Table[20];
Table * pTable = new Table;
for( Row* pRow = *pTable; pRow != *pTable+_countof(*pTable); ++pRow ) {
for( Cell* pCell = *pRow; pCell != *pRow + _countof(*pRow); ++pCell ) {
... do something with cells.
}
}
You can define a vector of vectors:
typedef my_type *my_pointer;
typedef vector<vector<my_pointer> > my_pointer2D;
Than create a class derived from my_pointer2D, like:
class PointersField: public my_pointer2D
{
PointsField(int n, int m)
{
// Resize vectors....
}
}
PointsField pf(10,10); // Will create a 10x10 matrix of my_pointer
I prefer to use the () operator. There are lots of reasons for this (C++ FAQs 13.10). Change the internal representation to a std::vector if you like:
template <class T, int WIDTH, int HIEGHT>
class Array2d
{
public:
const T& operator ()(size_t col, size_t row) const
{
// Assert col < WIDTH and row < HIEGHT
return m_data [( row * WIDTH + col)];
}
T& operator ()(size_t col, size_t row)
{
// Assert col < WIDTH and row < HIEGHT
return m_data [( row * WIDTH + col)];
}
private:
T m_data[WIDTH * HIEGHT];
};
You can use it like this:
Array2d< Object*, 10, 10 > myObjectArray;
myObjectArray(5,6) = new Object();
See my code. It works on my FC9 x86_64 system:
#include <stdio.h>
template<typename t>
struct array_2d {
struct array_1d {
t *array;
array_1d(void) { array = 0; }
~array_1d()
{
if (array) {
delete[] array;
array = 0;
}
}
t &operator[](size_t index) { return array[index]; }
} *array;
array_2d(void) { array = 0; }
array_2d(array_2d<t> *a) { array = a->array; a->array = 0; }
void init(size_t a, size_t b)
{
array = new array_1d[a];
for (size_t i = 0; i < a; i++) {
array[i].array = new t[b];
}
}
~array_2d()
{
if (array) {
delete[] array;
array = 0;
}
}
array_1d &operator[](size_t index) { return array[index]; }
};
int main(int argc, char **argv)
{
array_2d<int> arr = new array_2d<int>;
arr.init(16, 8);
arr[8][2] = 18;
printf("%d\n",
arr[8][2]
);
return 0;
}
Effo UPD: a response to "Isn't that an array of pointers to arrays?", adding the example of array of pointers, very simple:
int main(int argc, char **argv)
{
array_2d<int*> parr = new array_2d<int*>;
int i = 10;
parr.init(16, 8);
parr[10][5] = &i;
printf("%p %d\n",
parr[10][5],
parr[10][5][0]
);
return 0;
}
Did I still misunderstand your question?
And you could even
typedef array_2d<int*> cell_type;
typedef array_2d<cell_type*> array_type;
int main(int argc, char **argv)
{
array_type parr = new array_type;
parr.init(16, 8);
parr[10][5] = new cell_type;
cell_type *cell = parr[10][5];
cell->init(8, 16);
int i = 10;
(*cell)[2][2] = &i;
printf("%p %d\n",
(*cell)[2][2],
(*cell)[2][2][0]
);
delete cell;
return 0;
}
It also works on my FC9 x86_64 system.