I've just tried:
class Test
{
public:
int iArray[][];
}
...is this not possible? Do I have to set a constant value?
like:
class Test
{
public:
const int iArray[5][4];
}
I want to define [x][y] later, just have the placements there. Else it wouldn't be "dynamic" and I don't want to use a vector because I want to be able to access the values by "X" and "Y".
I think better way to achieve this is to use pointers. You can do like this.
#include <cstdlib>
#include <iostream>
using namespace std;
class PointerTest {
private:
int** array;
int x, y;
public :
void setValue(int row, int col,int value);
int getValue(int row, int col);
PointerTest(int row, int col);
~PointerTest() {
for(int i=0;i<x;i++) {
delete array[y];
}
}
};
PointerTest::PointerTest(int row, int col) {
x=row, y=col;
for(int i=0;i<row;i++) {
*array=new int[col];
}
}
void PointerTest::setValue(int row, int col, int value) {
*(array[row])=value;
}
int PointerTest::getValue(int row, int col) {
return *(array[row]);
}
int main(int argc, char *argv[])
{
PointerTest* t=new PointerTest(4,5);
t->setValue(0,0,464);
cout<<"The value in array: "<<t->getValue(0,0)<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
What about
tempalte <int N1, int N2> class Test
{
public:
int iArray[N1][N2];
};
?
What about putting a std::vector in a vector?
std::vector< std::vector< const int > > iArray;
There aren't many reason to use "plain" arrays in C++.
If you want to decide int iArray[][]; size later then you can use vector< vector<int> > iArray;.
The other way is to use nested new[], which would be little complex.
No this is not possible. But you can have a pointer in your class like
int **ptr;
and then in the constructor or where ever allocate the memory for your array with
ptr = (int **)malloc( the size you want );
or with the "new[]"-operator in C++.
but if you are using C++ .. the best way is to use:
std::vector< std::vector< int >> array;
class Test
{
public:
Test()
{
iArray = new int*[5];
for(int i = 0; i < 5; i++)
iArray[i] = new int[4];
}
~Test()
{
for(int i = 0; i < 5; i++)
delete[] iArray[i];
delete[] iArray;
}
int** iArray;
};
Will allow you to allocate a 2d int array at runtime (in this example it is a 5x4), but in all honestly I would use vectors as pointed out by some other posters, you don't need to worry about freeing the memory afterwards like you do with the use of new.
Related
I need to convert a plain double C-array to a VectorXd*. I found Map class that seems to do the job but there's something I didn't understand.
class A {
private:
VectorXd *jpos_;
public:
int init( double *v, int len )
{
// Here I would like to assign v to jpos_ in an efficient way
// (something like a pointer assignment without allocation or vector iterations)
// Note that length of v is len
}
};
I tried the following but it doesn't work:
int A::init( double *v, int len )
{
jpos_ = &VectorXd::Map( v, len );
}
or
int A::init( double *v, int len )
{
jpos_ = &Map<VectorXd>( v, len );
}
What's wrong?
Thanks.
Emanuele
If you want to map an array by means of Eigen::Map, your member jpos_ should be of type Eigen::Map:
class A
{
private:
Eigen::Map<Eigen::VectorXd> jpos_;
public:
A(double* v, int len) : jpos_ {v, len} {}
};
If you need to keep the VectorXd, you need to copy the values to the vector. It is a bit strange to see VectorXd*. It's similar like std::vector<double>*. I would recommend not using VectorXd*.
class A
{
private:
Eigen::VectorXd jpos_;
public:
A(double* v, int len) : jpos_ {v}
{
for (int i=0; i<len; ++i)
jpos_(i) = v[i];
}
};
EDIT:
If you really need VectorXd*, you can allocate one with new (and don't forget to delete it).
I would like to use template to specify sizes in functions. Let me give you an example.
I can do this:
int sub (int a[2][2]) {
}
int main () {
int a[2][2];
sub(a);
}
I can do this:
template<int size2>
int sub (int a[][size2]) {
}
int main () {
int a[2][2];
sub(a);
}
But what I would like is this:
template<int size1, int size2>
int sub (int a[size1][size2]) {
}
int main () {
int a[2][2];
sub(a);
}
How could I?
The better option is probably to use std::array, if you have C++11 support, or std::vector, if not. If you really want to use C-style arrays, you can pass them by reference, using the following syntax.
template<size_t size1, size_t size2>
int sub (int (&a)[size1][size2]) {
// ...
}
int main() {
int a[2][2];
sub(a);
}
As Brian Bi already wrote, the best way to go is to use std::array.
But to answer your question, it is halfway possible to do what you want.
When you use a C-style 2D array as an argument to a function, it decays to a pointer to an array of the second dimension. For example int a[6][6] decays to int (*a)[6], so the first dimension is hidden and means nothing to the compiler. The second dimension however, can be used as template parameters and can be deduced.
For example:
template<int S>
void func(int (*a)[S])
{
cout << S << endl;
}
and then:
int a[66][67];
func(a);
prints "67".
Here is another way (sub<2,2>:
template<int size1, int size2>
int sub (int a[size1][size2]) {
}
void main(int argc, char **argv)
{
int a[2][2];
sub<2,2>(a);
}
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];
}
The structure is defined as
struct state{
string node_name;
int node_no;
int node_val;
int occupant;
vector<int>node_con;
};
state s[100][100]
I want to send it to a function along with i and j values , where s[i][j] , (i->rows , j-> columns) . How will the struct be sent with both i and j ?
This way
void f(StructName (*a)[100], int i, int j) {
}
Please read about two dimensional arrays and pointer to arrays. Alternatively in C++ you can pass it by a reference, which will make it not decay to its first element
void f(StructName (&a)[100][100], int i, int j) {
}
in C there is no way (AFAIK)
in C++ you could do this
template <class T, int N, int M>
void f(T (&a)[N][M])
{
//...
}
Alternatively, you could pass the dimensions manually, or hard-code them
In C, you can wrap it up in another structure :-)
I see stuff that doesn't look like C in your code ...
struct state {
string node_name;
int node_no;
int node_val;
int occupant;
vector<int>node_con;
};
struct wrap {
int i;
int j;
struct state (*ps)[];
};
int main(void) {
struct state s[100][100];
struct wrap x;
x.i = 100;
x.j = 100;
x.ps = s;
fx(x);
return 0;
}
You mean passing an array of structures. I think it should be this:
struct state{
string node_name;
int node_no;
int node_val;
int occupant;
vector<int>node_con;
};
state s[100][100];
void doSomething(state theState[][100], int i, int j)
{
cout << theState[i][j].node_name << endl;
}
int main()
{
s[0][1].node_name = "s[0][1]";
doSomething(s, 0, 1);
}
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