Rewrite This Malloc Using New For 2D Array - c++

After some trial and error I found a way to malloc a 2D array so it is contiguous in memory, equivalent to the non-dynamic case.
int numRows =2;
int numCols = 4;
int (*p)[numCols];
p = (int (*)[numCols]) malloc(sizeof(int)*numRows*numCols);
So p is now basically the same as if I had done int p[2][4] - except it's on the heap instead of the stack.
2 Questions:
Do I just need to call free(p) to free the memory? No looping?
How would I convert this to using new, instead of malloc?
I tried
p = new (int (*)[4])[2];
But that gave the error:
error: cannot convert int (**)[4] to int (*)[4] in assignment

Here's a class template that uses one std::vector to hold a contiguous buffer, and size-aware proxy objects to access array elements dimension-by-dimension:
template<typename T>
class TwoDArray {
private:
std::size_t n_rows;
std::size_t n_cols;
std::vector<T> buf;
public:
class OneDArrayProxy {
private:
T *rowptr;
std::size_t colsize;
public:
OneDArrayProxy(const T *rp, std::size_t cs) : rowptr(const_cast<T *>(rp)), colsize(cs) {}
T const &operator[](std::size_t index) const {
return rowptr[index];
}
T &operator[](std::size_t index) {
return rowptr[index];
}
std::size_t size() const { return colsize; }
};
TwoDArray(std::size_t rows, std::size_t cols) : n_rows(rows), n_cols(cols), buf(rows * cols) {}
TwoDArray() : TwoDArray(0, 0) {}
OneDArrayProxy operator[](std::size_t index) const {
return OneDArrayProxy(&buf[index * n_cols], n_cols);
}
std::size_t rows() const { return n_rows; }
std::size_t columns() const { return n_cols; }
};
Usage example:
int main()
{
TwoDArray<int> arr(9, 5);
for (std::size_t i = 0; i < arr.rows(); i++) {
for (std::size_t j = 0; j < arr.columns(); j++) {
arr[i][j] = i * 10 + j;
}
}
for (std::size_t i = 0; i < arr.rows(); i++) {
// you can use the array element's 'size()' function instead of 'columns()'
for (std::size_t j = 0; j < arr[i].size(); j++) {
std::cout << arr[i][j] << " ";
}
std::cout << std::endl;
}
}

You can't do that in C++. Your malloc() code is perfectly valid C, but not valid C++. And it won't work with new.
C++ requires array types to have constant size, C allows arrays types of dynamic size. There is only an exception for 1D arrays, which may be allocated with dynamic size in C++, but that's it. In a 2D array, the second size must be known at compile time.
This is the one point at which C is much more powerful than C++.
It takes a bit to convince g++ to follow the standard in this regard, but compiling this little program
#include <stdlib.h>
int main(int argc, char** args) {
int (*foo)[argc];
}
with g++ -pedantic -std=c++11 foo.cpp dutifully produces the error message:
foo.cpp: In function ‘int main(int, char**)’:
foo.cpp:4:17: warning: ISO C++ forbids variable length array ‘foo’ [-Wvla]

1) Yes, you could just call free()
But attention, you are doing pointer aliasing (2 pointers to different types, int and int[] with the same address), which can cause subtle optimisation bugs. And in C++ it's a very bad practice to use malloc(), and numcols should be const.
2) The way you can do this in C++ would be to use [<array>][2] if the size to be known at compile time:
array<array<int, 4>,2> a;
The more flexible alternative is to use vectors which allow for dynamic size and resizing:
vector <vector <int>> b(2, vector<int>(4));
3) With new you could also do :
p = new (int[2][4]);
The first dimension could also be variable, but the second has to be a constant. But I'd encourage you to use one of the standard containter alternative.

Related

C++11 dynamically allocated variable length multidimensional array

I've been trying to create a variable length multidimensional array. As I understand, you can't create variable length arrays on the stack, but you can create 1D variable length arrays in C++ using dynamic allocation. Correct me if this is a compiler extension, but it seems to work fine on clang and gcc with --pedantic set.
int size = 10;
int *ary = new int[size]();
I tried to extend the concept to multidimensional arrays. Here are my results. The problem with possiblity 1 and 2 is that they require a constexpr and do not work with variable sizes. Is it possible to make either of them accept a variable as its size? I put possibility 3 as I am aware of it, but it lacks [][] access, which is what I'm looking for.
constexpr int constSize = 10;
//Possibility 1: Only works in C++11
//Creates CONTIGUOUS 2D array equivalent to array[n*n], but with [][] access
int (*ary1)[constSize] = new int[constSize][constSize]();
delete [] ary1;
//Possibility 2:
//Really horrible as it does NOT create a contiguous 2D array
//Instead creates n seperate arrays that are each themselves contiguous
//Also requires a lot of deletes, quite messy
int **ary2 = new int*[constSize];
for (int i = 0; i < n; ++i)
ary2[i] = new int[constSize];
for (int i = 0; i < n; ++i)
delete [] ary2;
delete [] ary2;
//Possibility 3:
//This DOES work with non-constexpr variable
//However it does not offer [][] access, need to access element using ary[i*n+j]
int *ary3 = new int[size*size];
delete [] ary3;
This will create a dynamically allocated 2D variable-length array, with dimensions w and h:
std::vector<std::vector<int>> ary4(w, std::vector<int>(h));
It can be accessed with [][]:
ary4[x][y] = 0;
However, it's not contiguously allocated. To get a contiguous array, here's one solution:
template<typename E>
class Contiguous2DArray
{
public:
Contiguous2DArray(std::size_t width, std::size_t height)
: array(width * height), width(width) {}
E& operator()(std::size_t x, std::size_t y)
{ return array[x + width * y]; }
private:
std::vector<E> array;
std::size_t width;
}
It can be used like this:
Contiguous2DArray<int> ary5(w, h);
ary5(x, y) = 0;
The number of dimensions is fixed, because the type of what [] returns changes based on the number of dimensions. Access is through both repeated [] and (...). The first mimics C-style array lookup. The (...) syntax must be complete (it must pass N args to an N dimensional array). There is a modest efficiency cost to support both.
Uses C++14 features to save on verbosity. None are essential.
Using an an n_dim_array with 0 dimensions will give bad results.
template<class T, size_t N>
struct array_index {
size_t const* dimensions;
size_t offset;
T* buffer;
array_index<T,N-1> operator[](size_t i)&&{
return {dimensions+1, (offset+i)* *dimensions, buffer};
}
template<class...Is, std::enable_if_t<sizeof...(Is) == N>>
T& operator()(size_t i, Is...is)&&{
return std::move(*this)[i](is...);
}
};
template<class T>
struct array_index<T,0> {
size_t const* dimension;
size_t offset;
T* buffer;
T& operator[](size_t i)&&{
return buffer[i+offset];
}
T& operator()(size_t i)&&{
return std::move(*this)[i];
}
};
template<class T, size_t N>
struct n_dim_array {
template<class...Szs, class=std::enable_if_t<sizeof...(Szs)==N>>
explicit n_dim_array( Szs... sizes ):
szs{ { static_cast<size_t>(sizes)... } }
{
size_t sz = 1;
for( size_t s : szs )
sz *= s;
buffer.resize(sz);
}
n_dim_array( n_dim_array const& o ) = default;
n_dim_array& operator=( n_dim_array const& o ) = default;
using top_level_index = array_index<T,N-1>;
top_level_index index(){return {szs.data(),0,buffer.data()};}
auto operator[]( size_t i ) {
return index()[i];
}
using const_top_level_index = array_index<const T,N-1>;
const_top_level_index index()const{return {szs.data(),0,buffer.data()};}
auto operator[]( size_t i ) const {
return index()[i];
}
template<class...Is,class=std::enable_if_t<sizeof...(Is)==N>>
T& operator()(Is...is){
return index()(is...);
}
template<class...Is,class=std::enable_if_t<sizeof...(Is)==N>>
T const& operator()(Is...is) const {
return index()(is...);
}
private:
n_dim_array() = delete;
std::array<size_t,N> szs;
std::vector<T> buffer;
};
live example
Does not support for(:) loop iteration. Writing an iterator isn't that hard: I'd do it in array_index.

how to computinally initialize a const array(make const look-up-tables)?

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;
}

c++ array[var][2] as a class member

I would like to have an array of unsigned integers within a class, and its size should be [var][2], so the user will be able to choose var in runtime.
Is there a better way than allocating a two dimensional array (an allocated array of pointers to allocated arrays)?
In the class I have:
unsigned int *(*hashFunc);
And in the initializing function:
hashFunc = new unsigned int*[var];
for(unsigned int i = 0; i<var; ++i)
hashFunc[i] = new unsigned int[2];
I want to only allocate once, and I think it should somehow be possible because I only have one unknown dimension (var is unknown but 2 I know from the beginning).
Thanks!
If the sizes are known at compilation time, you should use std::array. If one of the dimensions are not known until runtime, you should use std::vector.
You can of course combine them:
std::vector<std::array<unsigned int, 2>> hashFunc;
The above declares hashFunc to be a vector of arrays, and the arrays is of size two and of type unsigned int, just like specified in the question.
Then to add a new inner array just use push_back of the vector:
hashFunc.push_back({{ 1, 2 }});
(And yes, double braces are needed. The outer to construct the std::array object, and the inner for the actual array data.)
Or if you want to set the size of the outer vector at once (for example if you (runtime) know the size beforehand) you could do e.g.
hashFunc = std::vector<std::array<unsigned int, 2>>(var);
Where var above is the size of the "first dimension". Now you can directly access hashFunc[x][y] where x is in range of var and y is zero or one.
(To answer the direct question.) You can declare the pointer as
int (*hashFunc)[2];
and allocate it in one shot as
hashFunc = new int[var][2];
There's two ways you can go about this. Either have a class with a bare pointer or encapsulate it with std::vector and std::array. Below is a sample of two possible implementations which do exactly the same.
#include <iostream>
#include <vector>
#include <array>
#include <stdexcept>
class TheClass {
public:
typedef int TwoInts[2];
TheClass(const std::size_t size) : m_size(size)
{
m_hashFunc = new TwoInts[m_size];
if (m_hashFunc == NULL) throw std::runtime_error("Ran out of memory.");
}
virtual ~TheClass()
{
delete [] m_hashFunc;
}
inline std::size_t size() const { return m_size; }
inline int& operator()(const std::size_t i, const std::size_t j) { return m_hashFunc[i][j]; }
inline const int& operator()(const std::size_t i, const std::size_t j) const { return m_hashFunc[i][j]; }
private:
std::size_t m_size;
TwoInts* m_hashFunc;
};
class AnotherClass {
public:
AnotherClass(const std::size_t size) : m_hashFunc(size)
{
// Nothing to do here.
}
// No destructor required.
inline std::size_t size() const { return m_hashFunc.size(); }
inline int& operator()(const std::size_t i, const std::size_t j) { return m_hashFunc[i][j]; }
inline const int& operator()(const std::size_t i, const std::size_t j) const { return m_hashFunc[i][j]; }
private:
std::vector<std::array<int, 2>> m_hashFunc;
};
int main(int argc, char *argv[]) {
if (argc < 2) return -1;
const std::size_t runtimesize = static_cast<std::size_t>(atoll(argv[1]));
const std::size_t i1 = rand() % runtimesize;
const std::size_t i2 = rand() % runtimesize;
TheClass instance1(runtimesize);
AnotherClass instance2(runtimesize);
instance1(i1,0) = instance2(i1,0) = 4;
instance1(i2,1) = instance2(i2,1) = 2;
std::cout << instance1(i1,0) << ' ' << instance2(i1,0) << std::endl;
std::cout << instance1(i2,1) << ' ' << instance2(i2,1) << std::endl;
std::cout << instance1.size() << std::endl;
std::cout << instance2.size() << std::endl;
// ... etc
return 0;
}

C++ Operator Overload Error

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];
}

dynamical two dimension array according to input

I need to get an input N from the user and generate a N*N matrix. How can I declare the matrix? Generally, the size of the array and matrix should be fixed at the declaration, right?
What about vector<vector<int>> ? I never use this before so I need suggestion from veteran.
A vector<vector<int>> (or vector<vector<int> >, for older compilers) can work well, but it's not necessarily the most efficient way to do things1. Another that can work quite nicely is a wrapper around a single vector, that keeps track of the "shape" of the matrix being represented, and provides a function or overloaded operator to access the data:
template <class T>
class matrix {
int columns_;
std::vector<T> data;
public:
matrix(int columns, int rows) : columns_(columns), data(columns*rows) {}
T &operator()(int column, int row) { return data[row*columns_+column]; }
};
Note that the C++ standard only allows operator[] to take a single operand, so you can't use it for this job, at least directly. In the example above, I've (obviously enough) used operator() instead, so subscripts look more like Fortran or BASIC than you're accustomed to in C++. If you're really set on using [] notation, you can do it anyway, though it's mildly tricky (you overload it in the matrix class to return a proxy, then have the proxy class also overload operator[] to return (a reference to) the correct element -- it's mildly ugly internally, but works perfectly well anyway).
Here's an example of how to implement the version using multiple overloads of operator[]. I wrote this (quite a while) before most compilers included std::vector, so it statically allocates an array instead of using a vector. It's also for the 3D case (so there are two levels of proxies involved), but with a bit of luck, the basic idea comes through anyway:
template<class T, int size>
class matrix3 {
T data[size][size][size];
friend class proxy;
friend class proxy2;
class proxy {
matrix3 &m_;
int index1_, index2_;
public:
proxy(matrix3 &m, int i1, int i2)
: m_(m), index1_(i1), index2_(i2)
{}
T &operator[](int index3) {
return m_.data[index1_][index2_][index3];
}
};
class proxy2 {
matrix3 &m_;
int index_;
public:
proxy2(matrix3 &m, int d) : m_(m), index_(d) { }
proxy operator[](int index2) {
return proxy(m_, index_, index2);
}
};
public:
proxy2 operator[](int index) {
return proxy2(*this, index);
}
};
Using this, you can address the matrix with the normal C++ syntax, such as:
matrix3<double, size> m;
for (int x=0; x<size; x++)
for (int y = 0; y<size; y++)
for (int z = 0; z<size; z++)
m[x][y][z] = x*100 + y * 10 + z;
An std::vector is normally implemented as a pointer to some dynamically allocated data, so something like a vector<vector<vector<int>>> will dereference two levels of pointers to get to each piece of data. This means more memory references, which tend to be fairly slow on most modern processors. Since each vector contains separately allocated data, it also leads to poor cache locality as a rule. It can also waste some space, since each vector stores both its allocated size and the size in use.
Boost implements matrices (supporting mathematical operations) in its uBLAS library, and provides usage syntax like the following.
#include <boost/numeric/ublas/matrix.hpp>
int main(int argc, char* argv[])
{
unsigned int N = atoi(argv[1]);
boost::matrix<int> myMatrix(N, N);
for (unsigned i = 0; i < myMatrix.size1 (); ++i)
for (unsigned j = 0; j < myMatrix.size2 (); ++j)
myMatrix(i, j) = 3 * i + j;
return 0;
}
Sample Code:
template<class T>
class Array2D
{
public:
Array2D(int a, int b)
{
num1 = (T**)new int [a*sizeof(int*)];
for(int i = 0; i < a; i++)
num1[i] = new int [b*sizeof(int)];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
num1[i][j] = i*j;
}
}
}
class Array1D
{
public:
Array1D(int* a):temp(a) {}
T& operator[](int a)
{
return temp[a];
}
T* temp;
};
T** num1;
Array1D operator[] (int a)
{
return Array1D(num1[a]);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Array2D<int> arr(20, 30);
std::cout << arr[2][3];
getchar();
return 0;
}
enter code here