We're trying to use a 2D vector because we want a 2D array that will grow dynamically.
We tried this:
In the class declaration:
vector<vector<double> > table;
But then table doesn't seem to be allocated. We get a segfault when we try to access members.
So then we tried this:
Class Declaration:
vector<vector<double> >* table;
Constructor:
table = new vector<vector<double> >;
But now we the way we accessed it before (with [][]) doesn't work.
We tried a dummy class with this:
class myClass {
public:
myClass();
~myClass();
vector<vector<double> > t;
};
myClass::myClass()
{
t = vector<vector<double> > (10, vector<double>(10));
}
But it wouldn't free properly and we got core dumps. Also when we tried to grow the array, we'd have expclitly construct each new row.
Ex:
t[50] = vector<double>(5);
t[50][10] = 10;
If we didn't do it like this, we'd get a segfault
You'll need to resize the tables before you access elements.
vector<vector<double> > table;
table.resize(10);
for (int i = 0; i < 10; ++i)
table[i].resize(20);
Make sure your vectors are large enough to store your elements. If a vector t has size N, the last element you can access is t[N-1].
t = vector<vector<double> > (10, vector<double>(10));
t[50] = vector<double>(5); // This is wrong! Vector size is 10, you access 50th.
t[50][10] = 10; // Wrong again! Vector size 5, you access 10th.
If you have Boost installed try using Boost Multi-array.
You can access the element in [][] manner by derefrencing.
Vector<vector<double>> *table ;
table = new vector<vector<double>> ( n, vector<double>( m, 0.0)) ;
cout << (*table)[i][j] ;
Most of the times, this works perfectly well.
Related
i am new to c++ and i am trying to create an Array from within a function with just the array size, [row][col], as the argument. I know you cannot return an array from a function in c++. I would allocate memory in these situations if i were to code in C. However, i am not sure what is the C++ way (:
I tried,
int** get2Darray(int row, int col){
int** randInts = new int[row][col]; //Invalid. Constant required.
return randInts;
}
Thanks.
EDIT: vector class does the trick, however, my program is heavily modular. I dont have access to the main program. My function should be called and a fresh array should be created and returned. Implementation should only be done inside this function
Either change int** randInts = new int[row][col]; into int* randInts = new int[row * col]; or define int** randInts as follows:
int** randInts = new int*[row];
for (int i = 0; i < row; ++i) {
randInts[i] = new int[col];
}
It's a C way, not a C++ way. In C++ you should use containers (e.g. a vector as suggested in the comments).
I have shown this using vector <vector<T> >, but you can also use Eigen matrix or boost::ublas::matrix
std::vector< std::vector<int> > foo(const int rows, const int cols)
{
std::vector< std::vector<int> > v;
v.resize(rows);
for (auto i = 0; i < rows; i++)
{
v[i].resize(cols);
}
return v;
}
This will return a matrix of desired dimensions, and all elements will be initialized to 0.
The std::move part invokes a behavior called move semantics. You can read up on it. It's basically a better way of returning objects across a function boundary.
For compatibility's sake, if you must have a native array, then do this :
std::vector< vector<int> > temp = foo(rows, cols);
int *v = &temp[0][0];
Now, you can implement the gymnastics to get the correct index inside of int *v. You don't need multiple indirection.
P.S. This implementation assumes that your compiler supports C++ 11.
I am trying to initialize a pointer (*vectorName) with a 2D vector 366 by 4.
Both
vector<int> *vectorName = new vector<int>(366, new vector<int>(4));
and
vector<int> *vectorName = new vector<int>(366, vector<int>(4));
do not work and give me the error
Error: no instance of constructor "std::vector, <_Ty, _Alloc>::vector [with_ty=int, _Alloc=std_allocator]"
argument types are (const int, std::vector>*)
What can I do?
This is happening within the main function.
vector<int> *vectorName = new vector<int>(366, vector<int>(4));
The above doesn't work because the vector constructor template (ignoring a few things) looks as follows:
vector <TYPE> (SIZE, variable of type TYPE);
And in vector<int>(366, vector<int>(4)), vector <int> (4) is not of type int.
To create a vector with 366 elements that are vector of ints of size 4:
vector<vector<int> > *vectorName = new vector<vector<int> >(366, vector<int>(4));
or, if you don't need a pointer: (which you quite possibly don't)
vector<vector<int> > vectorName(366, vector<int>(4));
As a side note, if it's a fixed size 2D vector, why are you using vector, and not just an array. This would be much simpler:
int arr[366][4];
I assume that you're trying to use a pointer to a vector in order to get a dynamic C-array of vectors. There's no reason to do that. You can use a vector of vectors instead:
vector< vector<int> >
You can initialize that like this:
vector< vector<int> > vec(4);
for (size_t i = 0; i < 4; ++i) {
vec[i].resize(366);
}
Usage example:
vec[3][365] = 3;
If however you really do want a pointer to such a vector:
vector< vector<int> >* vec = new vector< vector<int> >(4);
for (size_t i = 0; i < 4; ++i) {
(*vec)[i].resize(366);
}
(*vec)[3][365] = 3;
If your size is constant and you're using a C++11 compiler, you can use an easier way, std::array:
array<array<int, 366>, 4> arr;
// Usage example
arr[3][365] = 3;
Or a pointer to a dynamically allocated one:
array<array<int, 366>, 4>* arr = new array<array<int, 366>, 4>;
// Usage example
(*arr)[3][365] = 3;
Are you trying to do this? This makes a 2D vector of vectors with int. It creates 366 vectors with a vector with size 4,where all items are initialized to zero. Now you have a 2D vector of 366 by 4.
vector<vector<int> > twod( 366, vector<int>(4,0));
and if you would like a pointer to this vector:
vector<vector<int> >* twodptr = &twod;
if you would really need this.
I have a function that takes in the number of rows and columns and initialises a vector of vector with default values of the object 'cell' and return the pointer to that vector.
//Cell class
class cell{
public:
int cost, parent;
cell(int cost = 0, int parent = 0) : cost(cost), parent(parent){}
}
//The initialisation function
vector<vector<cell> >* init_table(int n_rows, int n_cols){
//Error line
vector<vector<cell> >* table = new vector<vector<cell>(n_cols)> (n_rows);
//Some(very few) special cells need a different value so I do that here
return table; //Return the pointer
}
It seems the compiler resolves (n_cols)> (n_rows) like a > operation and not create n_cols copies of cell objects and n_rows copies of vector objects. How can I initialise the vector without manually looping through and pushing default valued cells in the vector?
Since C++ compilers usually have return value optimization, you can just do simply
vector<vector<cell> > init_table(int n_rows, int n_cols)
{
return vector<vector<cell> >(n_rows, vector<cell>(n_cols));
}
and writing
vector<vector<cell> > my_table = init_table(int n_rows, int n_cols);
will be as efficient as "new"-ing a vector, but this is safer.
Oh I now get it. I should initialise the outer vector with the inner vector through it's constructor like
vector<vector<cell> >* table = new vector<vector<cell> > (n_rows, vector<cell>(n_cols));
and not as a template parameter. It is working now.
I've got a class, and part of the input into the class is a vector (called Data) of variable length (lets say it has length N). I've included this after the function:
N = data_->size();
In the private section of the class, I want to declare an array double A[N][N];. However, when I try to do this, I get something saying
error: "N is not a type name, static, or enumerator".
How do I create the array A[N][N]?
Sorry if this is already explained somewhere else, as I'm very new to c++, so wouldn't even know what to look for!
Edit -- attached code:
class foo {
public:
foo (std::vector &data)
: data(data_)
{
N = data_->size();
M = /* four times the last member of data (which is a vector of positive integers)*/
}
private:
double A[M][M];
void foo(void)
{
for (std::size_t i=1; i<=M; ++i)
{
A[i][i] = 1;
}
}
};
Hope that makes some sort of sense... How would I be able to define A[M][M]? Maybe it's not possible to do it for M as M is a function of the data. If not possible for M, is it possible for N?
One possibility I can think of is that I can make A a std::vector< std::vector<double> > A and then push a lot of 0's or something into it, and THEN modify the values...
if you´re using the std::vector class you must creates the vector in a function of the data_ class (like the constructor, for example), using this sentence:
A = vector<vector<double> >(N, vector<double>(N, 0));
The first parameter of the parentheses is the size of the vector and the second is the type of data on it.
Sorry for my english, i´m spanish and my english isn´t very good.
You cannot do that. Arrays are types, and they have to be known at compile time. This includes their sizes. So you cannot have a dynamic array as part of your class. The closest thing you get is a pointer to manually allocated array, but that is in fact essentially a std::vector. So perhaps the easiest solution is to just have a vector of vectors, or perhaps a single vector of size N * N that you access in strides j + N * i.
Example:
std::vector< std::vector<int> > v(N, std::vector<int>(N));
Or:
std::vector< std::vector<int> > v;
//...
v.resize(N, std::vector<int>(N));
Access: v[2][4] = 8;
Update: Since you edited your answer, you can write something like this to get you an N * 4n vector, where data.back() == n:
std::vector<unsigned int> data = get_data(); // given!
std::vector< std::vector<double> > v(data.size(), std::vector<double>(4 * data.back()));
Hmmm...several issues here...
Neither N nor M are declared (either in the constructor or as members of foo)
You are trying to initialize a member data that is not declared (and you may mean data_(data) as the syntax is member(expression), not expression(member))
The argument to your constructor is an incomplete type: it needs to be std::vector< sometype >; if you want it to be generic you'll need to use templates or get some help from boost
You are not initializing the only member variable that you have declared (A)
void foo(void) is a problem because it is not the correct syntax for a constructor (which has no type) but uses the class name
Let's build up to something closer to what you want
Start with a class foo:
class foo {
};
with a constructor taking a single argument of type std::vector<double>
class foo {
public:
foo(std::vector<double> &data);
};
you want to initialize a member variable with the data
class foo {
private:
std::vector<double> data_;
public:
foo(std::vector<double> &data)
:data_(data)
{};
};
At this point I'll note that I would generally not put the definition of a non-trivial constructor in the class declaration, but in a implementation file instead, and consequently I would be able to put the declaration of member variable beneath the public section with the declaration of the constructor. But for compactness I'll leave this way here.
You want to capture and store the size of the data
class foo {
private:
std::vector<double> data_;
size_t N;
public:
foo(std::vector<double> &data)
:data_(data)
,N(data.size())
{};
};
At this point we still haven't made that multi-dimensional storage that you want, but now you have some decisions to make about how to manage the storage. If you use Kerrek SB's approach this looks something like
class foo {
private:
std::vector<double> data_;
size_t N;
std::vector< std::vector<double> > A;
public:
foo(std::vector<double> &data)
:data_(data)
,N(data.size())
,A()
{
A.resize(N);
for (size_t i=0; i<N; ++i) {
A[i].resize(N);
}
};
};
You need to create it dynamically, using a smart pointer if you do not want to manage memory yourself.
double **A;
in the constructor:
A = new double *[N];
for(i=0;i<N;++i)
{
A[i] = new double [N];
}
Not that you have to call delete in your destructor and now to obey the rule of three you have to have a copy constructor and a assignment operator... Using a smart pointer is better here: see the Boost smart pointer help page.
I have following std::vector declaration:
std::vector<std::vector<std::vector<int> > > m_input;
I am initializing it as follows:
m_input.resize (100);
m_output.resize(100);
for (int i = 0; i < 100; ++i) {
m_input [i].resize(100);
m_output[i].resize(100);
for (int j = 0; j < 100; ++j){
m_input [i][j].resize(100);
m_output[i][j].resize(100);
}
}
How can I achieve this via the member initializer list?
std::vector<T> has a constructor that takes two arguments, a number of elements and an initial value. In your case, you want to initialize m_input with 100 copies of a std::vector<std::vector<int> > , so it'd be : m_input(100, X). Now, that X in turn is a vector of 100 std::vector<int>, which in turn contains a hundred ints:
: m_input(100, std::vector<std::vector<int> >(100, std::vector<int>(100, 0)))
my_class::my_class()
: m_input(100, std::vector< std::vector<int> >(100, std::vector<int>(100) ))
{
}
That said, implementing a multi-dimensional field should be done by projecting into a one-dimensional one, as Viktor said in his comment to the question.
If you can assert that your vector dimensions are going to be of a fixed length, then why not use std::array?
For example:
std:array<std::array<std::array<int, 100>, 100>, 100>
That way you can take advantage of all the memory being contiguously allocated (as hinted at by Viktor_Sehr in the comments), without the added implementation woes of accessing a 1-dimensional array in a 3-dimensional way.