I have a two dimensional smart pointer array of doubles. I can assign values to it, and display it, but I am having trouble passing it to a function that takes double** as an input. A simple get() does not work.
#include <iostream>
#include <memory>
using namespace std;
# define DIM1 3
# define DIM2 4
void funcCall(double** item)
{
cout<< "Test function.";
}
int main() {
std::unique_ptr<std::unique_ptr<double[]>> myArray(new std::unique_ptr<double[]>[DIM1]);
for (int i = 0; i < DIM1; i++)
{
myArray.get()[i].reset(new double[DIM2]);
}
std::cout<<"Assign values"<<std::endl;
for (int i = 0; i < DIM2; i++)
{
for (int j = 0; j < DIM1; j++)
{
myArray.get()[j][i] = (j+1)*(i+1);
}
}
funcCall(myArray.get());
return 0;
}
When I compile this, I get:
error: cannot convert 'std::unique_ptr<std::unique_ptr<double []> >::pointer {aka std::unique_ptr<double []>*}' to 'double**' for argument '1' to 'void funcCall(double**)' funcCall(myArray.get())
void funcCall(std::unique_ptr<std::unique_ptr<double[]>> & arr)
Should do what you want, but...
but...
It sounds like you are trying to reinvent the wheel. Don't do that. Unless this is for an assignment or personal education, in that case go nuts.
Instead, use one of the built-in containers.
Because DIM1 and DIM2 are constant, you can use
std::array<std::array<double, DIM2>,DIM1> myArray;
and
void funcCall(std::array<std::array<double, DIM2>,DIM1> arr)
But odds are pretty good you want a dynamic solution. In that case, try
std::vector<std::vector<double>> myArray(DIM1, std::vector<double>(DIM2));
and
void funcCall(std::vector<std::vector<double>> arr)
but...
This is a sucker bet, to be honest. An array of arrays or a vector of vectors are not contiguous in memory so the computer has to hop around in storage, wasting time on unnecessary cache misses and the time spent loading and possibly reloading cache often take longer than the computations involved. All the 133t math in the world can't help you at this point because you've become gated by IO, and IO is sssssssssslllloooowwwwwwww.
What you really want is one nice 1 dimensional array that's indexed manually. with row * number of columns + column. Sure, manual index looks like extra work, but stop and think: How much math is the compiler doing in the background to make you array work, hmmm? Probably about the same. You just don't get to see it.
Let's stuck with std::vector for now, but the same applies to std::array or even a good ol' static array or a dynamic inside a smart pointer.
std::vector<double> myArray(DIM1*DIM2);
Using this is relatively simple:
myArray[row*DIM2 + column];
The function is:
void funcCall(std::vector<double> arr)
But this is easily wrapped in a class and simplified further:
class matrix
{
private:
std::vector<double> myArray;
size_t nrRows;
size_t nrColumns;
public:
matrix(size_t rows, size_t columns):
myArray(rows*columns), nrRows(rows), nrColumns(columns)
{
}
double& operator()(size_t row, size_t column)
{
return myArray[row* nrColumns + column];
}
double operator()(size_t row, size_t column) const
{
return myArray[row* nrColumns + column];
}
};
Construction:
matrix mat(DIM1, DIM2);
and usage:
double d = mat(1,2);
or
mat(2,1) = 3.14;
The types of the call and the function header don't match. You can't treat a unique_ptr as a regular pointer.
One solution is to change your function definition to:
void funcCall(std::unique_ptr<double[]> *item)
Related
In Matlab or NumPy it's very easy to create numerical arrays which are rectangular, multidimensional and dynamic. Those classes also have nice indexing functionality. Furthermore, they have data stored in one linear buffer.
I'm looking for something similiar in C++, syntax could be for example:
DoubleArray arr(size_x, size_y);
arr[x][y] = 5;
double * ptr = arr.getRawData() // returns the underlying linear storage
I think C++ does not offer anything built-in to do so. The only library I know is Eigen, but it has the drawback that matrices/arrays are always 2-dimensional.
Is there a good and easy way to achieve what I want? Most important is that I do not have to mess around manually with indexing, and that data is stored in one buffer (vs. vector of vectors).
I would guess that C++ does not offer a built-in multidim array, because it is rather easy to write one but how it should be implemented depends on your requirements. I was curious on how one could get such a multidimensional array and came up with this:
template <int DIMS>
struct multidimarray {
typedef int value_type;
value_type* data;
int* dimensions;
multidimarray(int* dims,value_type* d) : dimensions(dims),data(d) {}
multidimarray<DIMS-1> operator[](int index){
int s = 1;
for (int i=1;i<DIMS;i++){ s *= dimensions[i];}
return multidimarray<DIMS-1>(dimensions+1,data+s*index);
}
};
template <> struct multidimarray<1> {
typedef int value_type;
value_type* data;
int* dimensions;
multidimarray(int* dims,value_type* d) : dimensions(dims),data(d) {}
value_type operator[](int index){ return *(data+index); }
};
It is not the most efficient implementation, at least the size of the subarrays should not be computed for each access. Also it would be more convenient to use, if a wrapper was added that handles creation and deletion of the data. However, it seems to work (no guarantee, not more tested than with the following code):
#include <vector>
#include <iostream>
int main(){
int imax = 4;
int jmax = 4;
int kmax = 3;
std::vector<int> d;
d.push_back(imax); d.push_back(jmax);d.push_back(kmax);
std::vector<int> data;
for (int i=0;i<100;i++){data.push_back(i);}
multidimarray<3> md = multidimarray<3>(&d[0],&data[0]);
for (int i=0;i<imax;i++){
for (int j=0;j<jmax;j++){
for (int k=0;k<kmax;k++){
std::cout << md[i][j][k] << std::endl;
}
}
}
}
Sorry for the lack of auto and brace initialization, but this is pre-C++11.
Oh well, and I just realized that the multidimarray<1>::operator[] should of course return a reference instead of a value.
As I mentioned above, requirements may wildly differ for your specific application. Nevertheless, I hope this helps ;)
Basically, my problem is: I have the user to define the size (N,M) of a 2D array and then I declare:
int matrix[N][M];
then I need to pass this uninitialized matrix to a function that reads some data from a .csv file and puts it into the matrix, so I tried:
void readwrite(int &matrix[N][], const int N, const int M){....};
int main(){
....
cin>>N;
cin>>M;
int matrix[N][M];
readwrite(matrix,N,M);
};
However, when i compile it, it gives me the following error: "N was not declared in this scope".
Any ideas of how to make this work?
Thank y'all!
What The OP is trying is so annoyingly difficult to get right and the benefits of pulling it off are so minuscule compared to the costs that... Well, I'll quote from the Classics.
The only winning move is not to play.
-Joshua, WarGames
You cannot safely pass a dynamically allocated 2D array in C++ into a function because you always have to know at least one dimension at compile time.
I could point over at Passing a 2D array to a C++ function because that looks like a good duplicate. I won't because it's referring to statically allocated arrays.
You can play silly casting games to force the array into the function, and then cast it back on the inside. I'm not going to explain how to do this because it is epic-class stupid and should be a firing offense.
You can pass a pointer to a pointer, int **, but the construction and destruction logic is a grotesque set of new and loops. Further, the end result scatters the allocated memory around the RAM, crippling the processors attempts at prediction and caching. On a modern processor if you can't predict and cache, you are throwing away the greater part of your CPU's performance.
What you want to do is stay one dimensional. A 1D array is easy to pass. The indexing arithmetic is dead simple and easy to predict. It's all one memory block so cache hits are more likely than not.
Making a 1D array is simple: Don't. Use std::vector instead.
std::vector<int> arr(rows*columns);
If you have to because the assignment spec says "No Vectors!" Well you're stuck.
int * arr = new int[rows*columns];
Note I'm using rows and columns not M and N. When faced with M and N which is which? Who knows, who cares, and why do this to yourself in the first place? Give your variables good, descriptive names and enjoy the time savings of being able to read your code when you are debugging it later.
The guts of usage are identical with array and vector:
int test = arr[row * columns + column];
Will recover the element in 2D space at [row][column]. I shouldn't have to explain what any of those variables mean. Death to M and N.
Defining a function is:
void function (std::vector<int> & arr, size_t rows, size_t columns)
or (yuck)
void function (int * arr, size_t rows, size_t columns)
Note that rows and columns are of type size_t. size_t is unsigned (a negative array size is not something you want, so why allow it?) and it is guaranteed to be big enough to hold the largest possible array index you can use. In other words it is a much better fit than int. But why pass rows and columns everywhere? The smart thing to do at this point is make a wrapper around an the array and its control variables and then bolt on a few functions to make the thing easier to use.
template<class TYPE>
class Matrix
{
private:
size_t rows, columns;
std::vector<TYPE> matrix;
public:
// no default constructor. Matrix is BORN ready.
Matrix(size_t numrows, size_t numcols):
rows(numrows), columns(numcols), matrix(rows * columns)
{
}
// vector handles the Rule of Three for you. Don't need copy and move constructors
// a destructor or assignment and move operators
// element accessor function
TYPE & operator()(size_t row, size_t column)
{
// check bounds here
return matrix[row * columns + column];
}
// constant element accessor function
TYPE operator()(size_t row, size_t column) const
{
// check bounds here
return matrix[row * columns + column];
}
// stupid little getter functions in case you need to know how big the matrix is
size_t getRows() const
{
return rows;
}
size_t getColumns() const
{
return columns;
}
// and a handy-dandy stream output function
friend std::ostream & operator<<(std::ostream & out, const Matrix & in)
{
for (int i = 0; i < in.getRows(); i++)
{
for (int j = 0; j < in.getColumns(); j++)
{
out << in(i,j) << ' ';
}
out << '\n';
}
return out;
}
};
Rough bash-out of what the array version would have to look like just to show the benefits of allowing vector to do its job. Not tested. May contain howlers. The point is a lot more code and a lot more room for error.
template<class TYPE>
class ArrayMatrix
{
private:
size_t rows, columns;
TYPE * matrix;
public:
ArrayMatrix(size_t numrows, size_t numcols):
rows(numrows), columns(numcols), matrix(new TYPE[rows * columns])
{
}
// Array version needs the copy and move constructors to deal with that damn pointer
ArrayMatrix(const ArrayMatrix & source):
rows(source.rows), columns(source.columns), matrix(new TYPE[rows * columns])
{
for (size_t i = 0; i < rows * columns; i++)
{
matrix[i] = source.matrix[i];
}
}
ArrayMatrix(ArrayMatrix && source):
rows(source.rows), columns(source.columns), matrix(source.matrix)
{
source.rows = 0;
source.columns = 0;
source.matrix = nullptr;
}
// and it also needs a destructor
~ArrayMatrix()
{
delete[] matrix;
}
TYPE & operator()(size_t row, size_t column)
{
// check bounds here
return matrix[row * columns + column];
}
TYPE operator()(size_t row, size_t column) const
{
// check bounds here
return matrix[row * columns + column];
}
// and also needs assignment and move operator
ArrayMatrix<TYPE> & operator=(const ArrayMatrix &source)
{
ArrayMatrix temp(source);
swap(*this, temp); // copy and swap idiom. Read link below.
// not following it exactly because operator=(ArrayMatrix source)
// collides with operator=(ArrayMatrix && source) of move operator
return *this;
}
ArrayMatrix<TYPE> & operator=(ArrayMatrix && source)
{
delete[] matrix;
rows = source.rows;
columns = source.columns;
matrix = source.matrix;
source.rows = 0;
source.columns = 0;
source.matrix = nullptr;
return *this;
}
size_t getRows() const
{
return rows;
}
size_t getColumns() const
{
return columns;
}
friend std::ostream & operator<<(std::ostream & out, const ArrayMatrix & in)
{
for (int i = 0; i < in.getRows(); i++)
{
for (int j = 0; j < in.getColumns(); j++)
{
out << in(i,j) << ' ';
}
out << std::endl;
}
return out;
}
//helper for swap.
friend void swap(ArrayMatrix& first, ArrayMatrix& second)
{
std::swap(first.rows, second.rows);
std::swap(first.columns, second.columns);
std::swap(first.matrix, second.matrix);
}
};
Creating one of these is
Matrix<int> arr(rows, columns);
Now passing the array around is
void func(Matrix & arr);
Using the array is
int test = arr(row, column);
All of the indexing math is hidden from sight.
Other references:
What is the copy-and-swap idiom?
What is The Rule of Three?
int &matrix[N][] - N has to be a compile-time constant, not just const and not at all a parameter. And reference to an array is declared like: int (&matrix)[size]
Try passing int **matrix, and you'll also need to change the way you create this array. Variable lenght arrays are not supported in C++, you'll need to allocate it's memory dynamically. Or rather, stick with std::vector, std::array if you knew the sizes at compile-time.
I have a program in which the object array's size is determined during the runtime, so it's dynamically allocated (2D array, read from file). I also have a function which takes these objects as parameters. The problem is if the function parameters are 2D arrays that are passed to the function the 2nd dimension should be determined. However, in my case it is not. My program won't compile since the prototype does not have the 2nd dimension mentioned.
Here is what I tried:
//global variables
int residentCount=0;
int hospitalCount=0;
Resident** residents;
Hospital** hospitals;
bool readFromFiles(const string, const string, const int); //sizes are determined in here
void print(Hospital*[hospitalCount], Resident*[residentCount]); //declaration issue
How can I solve this?
You are programming in C++, so you should:
avoid dynamic allocation and handling memory management on your own always when it's possible
take advantage of objects with automatic storage duration instead, follow RAII idiom
avoid using C-style arrays and actually avoid writing C code that is just compilable as C++ in general
use great features that C++ provides, especially those bundled within STL
avoid using global variables when local equivalents suffice
This is how it could look like:
typedef std::vector<Resident> Residents;
typedef std::vector<Hospital> Hospitals;
// passing by const reference:
void print(const std::vector<Hospitals>&, const std::vector<Residents>&);
int main()
{
std::vector<Hospitals> hospitals;
std::vector<Residents> residents;
...
} // <-- lifetime of automatics declared within main ends here
Note that hospitals and residents will be objects with automatic storage duration, usable in similar manner than your C-style 2D arrays. When the execution goes out of the scope of main, these vectors are destructed and memory, where their elements (including elements of their elements) resided before is automatically cleaned up.
Also note that I suggest you to pass by const reference, i.e. const std::vector<Hospitals>&, which prevents the copy of passed object being created and const keyword explicitely tells to the caller: "Although you pass this object by reference, I will not change it."
Just pass a pointer to the first element of the array and the dimensions, that's enough, example:
void PrintHospitals(Hospital* Hospitals, size_t HospitalRows, size_t HospitalColumns)
{
size_t i, j;
Hospital* hospital;
for (i = 0; i < HospitalRows; i++)
for (j = 0; j < HospitalColumns; j++)
{
hospital = Hospitals + HospitalColumns * i + j;
PrintHospital(hospital);
}
}
int main()
{
Hospital hospitals[10][20];
// ...
PrintHospitals(&hospitals[0][0], 10, 20);
return 0;
}
Here is a solution using templates to create two-dimensional array wrappers for existing data:
template<typename T>
class Array2d {
public:
int Rows;
int Cols;
T** Data;
Array2d(int rows, int cols, T** data) :
Rows(rows),
Cols(cols),
Data(data) { }
};
void print(Array2d<Hospital> h, Array2d<Resident> r) {
for (int i = 0; i < h.Rows; i++) {
for (int j = 0; j < h.Cols; j++) {
//Print Data[i][j] element here
}
}
// Other print code
}
int main()
{
Resident** residents;
Hospital** hospitals;
//Init data arrays
Array2d<Hospital> h(10, 10, hospitals);
Array2d<Resident> r(10, 10, residents);
print(h, r);
}
I am reading a book on Safe C++. Here, the author mentioned how to avoid out of bound array reading. Here, it is mentioned how we can avoid out of bound array reading for multi dimension arrays. Here author used operator() function as shown in following link instead of operator[] and gave following explanation.
https://github.com/vladimir-kushnir/SafeCPlusPlus/blob/master/scpp_matrix.hpp
Note here that to access multidimensional array, we either need to use multiple [] operators, such as matrix[i][j], or a single () operator, such as matrix(i,j).
The first approach can be achieved if we had the [] operator return a T* pointer to the zeroth element of i-th row. However, this denies us the diagnosis of a column index out of bounds, which defeats the purpose of catching bugs at run-time. We could, of course, create some template class that would include a smart reference to a row, return an instance of using the first operator([i]), and then use the bounds check in the second operator ([j]).
My question what does author mean by "create some template class that would include a smart reference to a row, return an instance of using the first operator([i]), and then use the bounds check in the second operator ([j])." ? Request to provide sample code how we can implement above logic in C++?
Thanks for your time and help.
The basic idea looks something like this:
#include <vector>
#include <iostream>
template <class T>
class matrix {
size_t cols;
size_t rows;
std::vector<T> data;
class row_proxy { // This class is the part the question really asked about
size_t row;
matrix &m;
public:
row_proxy(matrix &m, size_t row) : row(row), m(m) {}
T &operator[](size_t col) {
if (row >= m.rows || col >= m.cols) // Note: row & col are indices not array count
throw std::logic_error("Bad index");
return m.data[row * m.cols + col];
}
};
public:
matrix(size_t cols, size_t rows) : rows(rows), cols(cols), data(rows*cols) {}
row_proxy operator[](size_t row) {
return row_proxy(*this, row);
}
};
int main() {
matrix<int> m(3, 3);
for (int i=0; i<3; i++) // fill the matrix with identifiable numbers
for (int j=0; j<3; j++)
m[i][j] = i * 100 + j;
for (int i=0; i<3; i++) { // show the content
for (int j=0; j<3; j++)
std::cout << m[i][j] << "\t";
std::cout << "\n";
}
try { // test the bounds checking.
m[4][1] = 21;
}
catch(std::logic_error &e) {
std::cerr << e.what();
}
return 0;
}
So, when we create a matrix, we save its size in rows and cols. When we use operator[] on the matrix, that doesn't attempt to directly return a reference to an item in the matrix -- rather, it returns an instance of a proxy class that keeps track of the row and the matrix, and provides an operator[] of its own.
So, when you use matrix[a][b], The first one just saves a and matrix into a proxy object. Then the [b] part gets invoked on that proxy object. That checks that both a and b are within the bounds we saved for the matrix, and if so returns a reference to the correct object in the vector. Otherwise, it throws an std::Logic_error (may not be the best choice -- just the first one that occurred to me).
I should add that there are quite a few variations on this general idea. Just for one example, you could specify the size of the array at compile time, but passing the sizes as template parameters. This can have some advantages -- for example, matrix<int, 2, 3> and matrix<int, 3, 2> are entirely different types, so you can't accidentally assign one to the other. It can also have some disadvantages (most obviously, you need to know the size at compile time or it won't work at all).
as in the title is it possible to join a number of arrays together without copying and only using pointers? I'm spending a significant amount of computation time copying smaller arrays into larger ones.
note I can't used vectors since umfpack (some matrix solving library) does not allow me to or i don't know how.
As an example:
int n = 5;
// dynamically allocate array with use of pointer
int *a = new int[n];
// define array pointed by *a as [1 2 3 4 5]
for(int i=0;i<n;i++) {
a[i]=i+1;
}
// pointer to array of pointers ??? --> this does not work
int *large_a = new int[4];
for(int i=0;i<4;i++) {
large_a[i] = a;
}
Note: There is already a simple solution I know and that is just to iteratively copy them to a new large array, but would be nice to know if there is no need to copy repeated blocks that are stored throughout the duration of the program. I'm in a learning curve atm.
thanks for reading everyone
as in the title is it possible to join a number of arrays together without copying and only using pointers?
In short, no.
A pointer is simply an address into memory - like a street address. You can't move two houses next to each other, just by copying their addresses around. Nor can you move two houses together by changing their addresses. Changing the address doesn't move the house, it points to a new house.
note I can't used vectors since umfpack (some matrix solving library) does not allow me to or i don't know how.
In most cases, you can pass the address of the first element of a std::vector when an array is expected.
std::vector a = {0, 1, 2}; // C++0x initialization
void c_fn_call(int*);
c_fn_call(&a[0]);
This works because vector guarantees that the storage for its contents is always contiguous.
However, when you insert or erase an element from a vector, it invalidates pointers and iterators that came from it. Any pointers you might have gotten from taking an element's address no longer point to the vector, if the storage that it has allocated must change size.
No. The memory of two arrays are not necessarily contiguous so there is no way to join them without copying. And array elements must be in contiguous memory...or pointer access would not be possible.
I'd probably use memcpy/memmove, which is still going to be copying the memory around, but at least it's been optimized and tested by your compiler vendor.
Of course, the "real" C++ way of doing it would be to use standard containers and iterators. If you've got memory scattered all over the place like this, it sounds like a better idea to me to use a linked list, unless you are going to do a lot of random access operations.
Also, keep in mind that if you use pointers and dynamically allocated arrays instead of standard containers, it's a lot easier to cause memory leaks and other problems. I know sometimes you don't have a choice, but just saying.
If you want to join arrays without copying the elements and at the same time you want to access the elements using subscript operator i.e [], then that isn't possible without writing a class which encapsulates all such functionalities.
I wrote the following class with minimal consideration, but it demonstrates the basic idea, which you can further edit if you want it to have functionalities which it's not currently having. There should be few error also, which I didn't write, just to make it look shorter, but I believe you will understand the code, and handle error cases accordingly.
template<typename T>
class joinable_array
{
std::vector<T*> m_data;
std::vector<size_t> m_size;
size_t m_allsize;
public:
joinable_array() : m_allsize() { }
joinable_array(T *a, size_t len) : m_allsize() { join(a,len);}
void join(T *a, size_t len)
{
m_data.push_back(a);
m_size.push_back(len);
m_allsize += len;
}
T & operator[](size_t i)
{
index ix = get_index(i);
return m_data[ix.v][ix.i];
}
const T & operator[](size_t i) const
{
index ix = get_index(i);
return m_data[ix.v][ix.i];
}
size_t size() const { return m_allsize; }
private:
struct index
{
size_t v;
size_t i;
};
index get_index(size_t i) const
{
index ix = { 0, i};
for(auto it = m_size.begin(); it != m_size.end(); it++)
{
if ( ix.i >= *it ) { ix.i -= *it; ix.v++; }
else break;
}
return ix;
}
};
And here is one test code:
#define alen(a) sizeof(a)/sizeof(*a)
int main() {
int a[] = {1,2,3,4,5,6};
int b[] = {11,12,13,14,15,16,17,18};
joinable_array<int> arr(a,alen(a));
arr.join(b, alen(b));
arr.join(a, alen(a)); //join it again!
for(size_t i = 0 ; i < arr.size() ; i++ )
std::cout << arr[i] << " ";
}
Output:
1 2 3 4 5 6 11 12 13 14 15 16 17 18 1 2 3 4 5 6
Online demo : http://ideone.com/VRSJI
Here's how to do it properly:
template<class T, class K1, class K2>
class JoinArray {
JoinArray(K1 &k1, K2 &k2) : k1(k1), k2(k2) { }
T operator[](int i) const { int s = k1.size(); if (i < s) return k1.operator[](i); else return k2.operator[](i-s); }
int size() const { return k1.size() + k2.size(); }
private:
K1 &k1;
K2 &k2;
};
template<class T, class K1, class K2>
JoinArray<T,K1,K2> join(K1 &k1, K2 &k2) { return JoinArray<T,K1,K2>(k1,k2); }
template<class T>
class NativeArray
{
NativeArray(T *ptr, int size) : ptr(ptr), size(size) { }
T operator[](int i) const { return ptr[i]; }
int size() const { return size; }
private:
T *ptr;
int size;
};
int main() {
int array[2] = { 0,1 };
int array2[2] = { 2,3 };
NativeArray<int> na(array, 2);
NativeArray<int> na2(array2, 2);
auto joinarray = join(na,na2);
}
A variable that is a pointer to a pointer must be declared as such.
This is done by placing an additional asterik in front of its name.
Hence, int **large_a = new int*[4]; Your large_a goes and find a pointer, while you've defined it as a pointer to an int. It should be defined (declared) as a pointer to a pointer variable. Just as int **large_a; could be enough.