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

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

Related

c++ how to initialize const elements of an array

i need a way to initialize const elements of an array for the program i am currently working on.
The problem is that i have to initialize these elements with a function, there is no way to do it like this:
const int array[255] = {1, 1278632, 188, ...};
because its alot of data i have to generate.
What i tried is to memcpy data to the const int's but that can't work and hasn't worked.
const int array[255];
void generateData(){
for(int i = 0; i < 255; i++) {
initializeSomehowTo(5, array[i]);
}
}
I hope you understand what i am trying, sorry if i doubled the question, i must have overlooked it.
How about this?
#include <array>
typedef std::array<int, 255> Array;
const Array array = generateData();
Array generateData(){
Array a;
for(int i = 0; i < a.size(); i++) {
initializeSomehowTo(a[i]);
}
return a;
}
The easiest approach is to get the filled array from a function and use that to initialize your const (or constexpr) object. However, built-in arrays can't be copied but std::array<T, N> be:
std::array<T, 255> array = initializeData();
If you need a built-in array, I can imagine initializing a static member of a class (template, actually) where the index is expanded from indices expanded from an std::make_index_sequence<255> and used as positional argument in the array, i.e., something along these lines:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <utility>
int some_function(std::size_t i) { return i; }
template <typename> struct initialized_array_base;
template <std::size_t... I>
struct initialized_array_base<std::index_sequence<I...>> {
static const int array[sizeof...(I)];
};
template <std::size_t... I>
int const initialized_array_base<std::index_sequence<I...>>::array[sizeof...(I)]
= { some_function(I)... };
struct initialized_array
:initialized_array_base<std::make_index_sequence<256>> {
};
int main() {
std::copy(std::begin(initialized_array::array),
std::end(initialized_array::array),
std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
}
You can create a writable array, initialize it, and, then, create a const reference to it.
int arry[255];
void generateData(){
for(int i = 0; i < 255; i++) {
initializeSomehowTo(5, arry[i]);
}
}
const int (&array)[255] = arry;

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

Return one dimension of an array?

How would I only return one dimension of an array, while ignoring the other?
Such as:
int map[4][8];
int MapManager::getMapX(int x)
{
return map[x];
}
The return type should be int* or int[], not int:
int* MapManager::getMapX(int x) {
return map[x];
}
Other than that, you are fine.
With a 2 dimensional array you will only be able to directly return a one dimensional array for the inner array by converting to a pointer, such as
int map[4][8];
int* MapManager::getMapX(int x)
{
return map[x];
}
For the other 'dimension', you will need to have another external array to copy to:
int* MapManager::getMapY(int y, int *outArray, int numElements)
{
for(int i = 0; i < numElements; i++) {
outArray[i] = map[i][y];
}
}
This array needs to be allocated with the correct size. (8 in this case).
The reason for this is that the array elements for the y 'column' are not contiguous in memory, but spread across several arrays (which are the 'x' rows). C arrays rely on this contiguous concept for accessing the elements.
Since none of the other answers here return an actual array (pointers are not arrays), I thought I might show how to really return an array. Or the closest thing possible, which is a reference to an array.
typedef int row_type[8];
row_type& MapManager::getMapX(int x) {
return map[x];
}
What's the point of this? The pointer works the same!
No, it doesn't. The pointer loses type information, namely, the size. You can make begin() and end() functions work with arrays, but you can't with pointers:
// pointer version
int* MapManager::getMapX_ptr(int x) {
return map[x];
}
row_type& row = getMapX(0);
// row is of type int(&)[8]
// notice the size is not lost in the type!
std::sort(begin(row), end(row));
// compiles fine! end() correctly finds the end of the row
int* ptr = getMapX_ptr(0);
// notice how ptr has no size information at all
std::sort(begin(ptr), end(ptr));
// can't possible be made to work!
You can't write end for int*.
template <typename T, std::size_t N>
T* end(T(&arr)[N]) {
return &arr[0] + N;
}
template <typename T>
T* end(T* ptr) {
// what here?
// guess?
// pick a random number?
}
You could create a special class that provides a strided view of an array. That is to say, it skips over values. Here's the beginnings of something like that:
template<typename T>
class StridedView
{
public:
StridedView(T * b, int stride, int count)
:begin_(b), stride_(stride), count_(count)
{}
template<int N>
StridedView(T (&arr)[N])
:begin_(arr), stride_(1), count_(N)
{}
T & operator[](int index)
{
return *(begin_ + index * stride_);
}
const T & operator[](int index) const
{
return *(begin_ + index * stride_);
}
int size() const { return count_; }
private:
T * begin_;
int stride_;
int count_;
};
Then you could have functions that can get you a row or a column as appropriate:
template<typename T, int R, int C>
StridedView<T> GetRow(T (&arr)[R][C], int row)
{
T * begin = (*arr) + (row * C);
return StridedView<T>(begin, 1, C);
}
template<typename T, int R, int C>
StridedView<T> GetColumn(T (&arr)[R][C], int column)
{
T * begin = (*arr) + column;
return StridedView<T>(begin, C, R);
}
Demo

Array with undefined size as Class-member

I'm searching for a way to define an array as a class-member with an undefined size (which will be defined on initialization).
class MyArrayOfInts {
private:
int[] array; // should declare the array with an (yet) undefined length
public:
MyArrayOfInts(int);
int Get(int);
void Set(int, int);
};
MyArrayOfInts::MyArrayOfInts(int length) {
this->array = int[length]; // defines the array here
}
int MyArrayOfInts::Get(int index) {
return this->array[index];
}
void MyArrayOfInts:Set(int index, int value) {
this->array[index] = value;
}
How can I achieve this behaviour ?
Why not just use std::vector<int>?
Proof Of Concept
Ok, inspired by UncleBens challenge here, I came up with a Proof-Of-Concept (see below) that let's you actually do:
srand(123);
for (int i=0; i<10; i++)
{
size_t N = rand() % DEMO_MAX; // capped for demo purposes
std::auto_ptr<iarray> dyn(make_dynamic_array(N));
exercise(*dyn);
}
It revolves around a template trick in factory<>::instantiate that actually uses a compile-time meta-binary-search to match the specified (runtime) dimension to a range of explicit static_array class template instantiations.
I feel the need to repeat that this is not good design, I provide the code sample only to show what the limits are of what can be done - with reasonable effor, to achieve the actual goal of the question. You can see the drawbacks:
the compiler is crippled with a boatload of useless statical types and create classes that are so big that they become a performance liability or a reliability hazard (stack allocation anyone? -> we're on 'stack overflow' already :))
at DEMO_MAX = 256, g++ -Os will actually emit 258 instantiations of factory<>; g++ -O4 will keep 74 of those, inlining the rest[2]
compilation doesn't scale well: at DEMO_MAX = MAX_RAND compilation takes about 2m9s to... run out of memory on a 64-bit 8GB machine; at MAX_RAND>>16 it takes over 25 minutes to possibly compile (?) while nearly running out of memory. It would really require some amounts of ugly manual optimization to remove these limits - I haven't gone so insane as to actually do that work, if you'll excuse me.
on the upside, this sample demonstrates the arguably sane range for this class (0..256) and compiles in only 4 seconds and 800Kb on my 64-bit linux. See also a down-scaled, ANSI-proof version at codepad.org
[2] established that with objdump -Ct test | grep instantiate | cut -c62- | sort -k1.10n
Show me the CODE already!
#include <iostream>
#include <memory>
#include <algorithm>
#include <iterator>
#include <stdexcept>
struct iarray
{
typedef int value_type;
typedef value_type* iterator;
typedef value_type const* const_iterator;
typedef value_type& reference;
typedef value_type const& const_reference;
virtual size_t size() const = 0;
virtual iterator begin() = 0;
virtual const_iterator begin() const = 0;
// completely unoptimized plumbing just for demonstration purps here
inline iterator end() { return begin()+size(); }
inline const_iterator end() const { return begin()+size(); }
// boundary checking would be 'gratis' here... for compile-time constant values of 'index'
inline const_reference operator[](size_t index) const { return *(begin()+index); }
inline reference operator[](size_t index) { return *(begin()+index); }
//
virtual ~iarray() {}
};
template <size_t N> struct static_array : iarray
{
static const size_t _size = N;
value_type data[N];
virtual size_t size() const { return _size; }
virtual iterator begin() { return data; }
virtual const_iterator begin() const { return data; }
};
#define DEMO_MAX 256
template <size_t PIVOT=DEMO_MAX/2, size_t MIN=0, size_t MAX=DEMO_MAX>
struct factory
/* this does a binary search in a range of static types
*
* due to the binary search, this will require at most 2log(MAX) levels of
* recursions.
*
* If the parameter (size_t n) is a compile time constant expression,
* together with automatic inlining, the compiler will be able to optimize
* this all the way to simply returning
*
* new static_array<n>()
*
* TODO static assert MIN<=PIVOT<=MAX
*/
{
inline static iarray* instantiate(size_t n)
{
if (n>MAX || n<MIN)
throw std::range_error("unsupported size");
if (n==PIVOT)
return new static_array<PIVOT>();
if (n>PIVOT)
return factory<(PIVOT + (MAX-PIVOT+1)/2), PIVOT+1, MAX>::instantiate(n);
else
return factory<(PIVOT - (PIVOT-MIN+1)/2), MIN, PIVOT-1>::instantiate(n);
}
};
iarray* make_dynamic_array(size_t n)
{
return factory<>::instantiate(n);
}
void exercise(iarray& arr)
{
int gen = 0;
for (iarray::iterator it=arr.begin(); it!=arr.end(); ++it)
*it = (gen+=arr.size());
std::cout << "size " << arr.size() << ":\t";
std::copy(arr.begin(), arr.end(), std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl;
}
int main()
{
{ // boring, oldfashioned method
static_array<5> i5;
static_array<17> i17;
exercise(i5);
exercise(i17);
}
{ // exciting, newfangled, useless method
for (int n=0; n<=DEMO_MAX; ++n)
{
std::auto_ptr<iarray> dyn(make_dynamic_array(n));
exercise(*dyn);
}
try { make_dynamic_array(-1); } catch (std::range_error e) { std::cout << "range error OK" << std::endl; }
try { make_dynamic_array(DEMO_MAX + 1); } catch (std::range_error e) { std::cout << "range error OK" << std::endl; }
return 0;
srand(123);
for (int i=0; i<10; i++)
{
size_t N = rand() % DEMO_MAX; // capped for demo purposes
std::auto_ptr<iarray> dyn(make_dynamic_array(N));
exercise(*dyn);
}
}
return 0;
}
Declare it as:
int* array;
Then you can initialize it this way:
MyArrayOfInts::MyArrayOfInts(int length) {
this->array = new int[length];
}
Don't forget to free the memory in the destrutor:
MyArrayOfInts::~MyArrayOfInts() {
delete [] this->array;
}
Is the class declaration complete ? If the constructor of the class takes the size of the array as an argument and you don't want to resize the array, then templatizing the class can give you runtime behaviour.
Now, we don't have to pass the size of the array as argument to the constructor.
template<size_t size>
class MyClass
{
public:
MyClass() { std::iota(arr_m, arr_m + size, 1); }
int operator[](int index) const
{
return arr_m[index];
}
int& operator[](int index)
{
return arr_m[index];
}
void Set(size_t index, int value)
{
arr_m[index] = value;
}
private:
int arr_m[size];
};
int main()
{
{
MyClass<5> obj;
std::cout << obj[4] << std::endl;
}
{
MyClass<4> obj;
std::cout << obj[3] << std::endl;
obj.Set(3, 30);
std::cout << obj[3] << std::endl;
}
}
In response to critics in the comments
I think many people fail to notice a crucial given in the question: since the question asks specifically how to declare an int[N] array inside a struct, it follows that each N will yield a distinct static type to the compiler.
As much as my approach is being 'critiqued' for this property, I did not invent it: it is a requirement from the original question. I can join the chorus saying: "just don't" or "impossible" but as a curious engineer I feel I'm often more helped by defining the boundaries of ust what is in fact still possible.
I'll take a moment to come up with a sketch of an answer to mainly UncleBen interesting challenge. Of course I could hand-waive 'just use template metaprogramming' but it sure would be more convincing and fun to come up with a sample1
1 only to follow that sample with a big warning: don't do this in actual life :)
The TR1 (or c++0x) type std::array does exactly that; you'll need to make the containing class generic to cater for the array size:
template <size_t N> struct MyArrayOfInts : MyArrayOfIntsBase /* for polymorphism */
{
std::array<int, N> _data;
explicit MyArrayOfInts(const int data[N])
{
std::copy(data, data+N, _data);
}
};
You can make the thing easier to work with by doing a smart template overloaded factory:
template <size_t N>
MyArrayOfInts<N> MakeMyArray(const int (&data)[N])
{ return MyArrayOfInts<N>(data); }
I'm working on this too for solving a dynamic array problem - I found the answer provided was sufficient to resolve.
This is tricky because arrays in functions from my reading do not continue after function ends, arrays have a lot of strange nuance, however if trying to make a dynamic array without being allowed to use a vector, I believe this is the best approach..
Other approaches such as calling new and delete upon the same pointed to array can/will lead to double free pending the compiler as it causes some undefined behavior.
class arrayObject
{
public:
arrayObject();
~arrayObject();
int createArray(int firstArray[]);
void getSize();
void getValue();
void deleting();
// private:
int *array;
int size;
int counter;
int number;
};
arrayObject::arrayObject()
{
this->array = new int[size];
}
arrayObject::~arrayObject()
{
delete [] this->array;
}