C++ object construction in a multidimensional dynamic array - c++

I am trying to create an nxn array of objects, but I do not know where to call their constructors. Here is my code:
class obj {
private: int x;
public: obj( int _x ) { x = _x; }
};
int main( int argc, const char* argv[] ) {
int n = 3; //matrix size
obj** matrix = new obj*[n];
for( int i = 0; i < n; i++ )
matrix[i] = new obj[n];
return 0;
}

If only the default constructor invocation is required, your code already calls it.
For a non-default constructor add a nested loop, like this:
for( int i = 0; i < n; i++ ) {
matrix[i] = new obj[n];
for (int j = 0 ; j != n ; j++) {
matrix[i][j] = obj(arg1, arg2, arg3); // Non-default constructor
}
}
A better approach is to use std::vector of obj if no polymorphic behavior is required, or of smart pointers to obj if you need polymorphic behavior.

If you really want to muck around with low-level memory management, then you can't - the array form of new doesn't allow you to pass arguments to the objects' constructors. The best you could do is to let them be default-constructed (adding a constructor to your class if necessary) and then loop through and reassign them. This is tedious and error-prone.
I'd suggest using higher-level classes; for dynamic arrays, use a vector:
std::vector<std::vector<obj>> matrix(n);
for (auto & row : matrix) {
row.reserve(n);
for (size_t i = 0; i < n; ++n) {
row.emplace_back(/* constructor argument(s) here */);
}
}
As a bonus, RAII means you don't need to delete all the allocations yourself, and it won't leak memory if any of this fails.

dasblinkenlight has already given quite a good answer, however, there is a second way to do it that's more efficient. Because, if you do (the code is taken from his answer)
matrix[i] = new obj[n];
for (int j = 0 ; j != n ; j++) {
matrix[i][j] = obj(arg1, arg2, arg3); // Non-default constructor
}
the following will happen:
Memory for n objects is allocated.
All n objects are default constructed.
For each object, a new object is custom constructed on the stack.
This object on the stack is copied into the allocated object.
The object on the stack is destructed.
Obviously much more than would have been necessary (albeit perfectly correct).
You can work around this by using placement new syntax:
matrix[i] = (obj*)new char[n*sizeof obj]; //Allocate only memory, do not construct!
for (int j = 0 ; j != n ; j++) {
new (&matrix[i][j]) obj(arg1, arg2, arg3); // Non-default constructor called directly on the object in the matrix.
}

Related

munmap_chunk(): invalid pointer in C++ program

I get an error "munmap_chunk(): invalid pointer", I don't know why. Problem appears when I use MultipliedByMatrix method. It can't properly delete the matrix that was created in this method.
#include "matrix.h"
Matrix::Matrix(int matr_size) {
size = matr_size;
Matr = new int *[size];
for(int i = 0; i < size; i++)
Matr[i] = new int[size];
for(int i = 0 ; i < size; i++)
for(int j = 0; j < size; j++)
Matr[i][j] = rand() % 100;
std::cout << "New matrix is created" << std::endl;
}
Matrix::~Matrix() {
for(int i = 0; i < size; i++)
delete[] Matr[i];
delete[] Matr;
Matr = NULL;
std::cout << "Matrix is deleted" << std::endl;
}
Matrix Matrix::MultipliedByMatrix(Matrix OtherMatr) {
Matrix new_matr = Matrix(this->GetSize());
int new_value;
for(int i = 0 ; i < size; i++)
for(int j = 0; j < size; j++) {
new_value = 0;
new_value += Matr[j][i] * OtherMatr.GetValue(i, j);
new_matr.SetValue(i, j, new_value);
}
return new_matr;
}
int Matrix::GetSize() {
return size;
}
int Matrix::GetValue(int i, int j) {
return Matr[i][j];
}
void Matrix::SetValue(int i, int j, int value) {
Matr[i][j] = value;
}
Did you write the Matrix class yourself? If so, I bet the problem is that you don't have a copy or move constructor. If so, the compiler will have generated one for you. This will copy the values of size and Matr but it won't create copies of the pointed-to arrays. When you write:
return new_matr;
this creates a new matrix (using the copy constructor - which just copies the pointer), and then calls the destructor of new_matr (which deletes the memory which is pointed to). The calling function is then dealing with junk memory, and when it tries to eventually delete the result, all hell will break loose
You also will need to write a move assignment operator.
Alternatively make Matr a std::vector<int> (of length 'size' squared), and write:
int Matrix::GetValue(int i, int j) {
return Matr[i*size+j];
}
(and similarly for other functions). std::vector has a proper copy and move constructor, and proper assignment behaviour - so it will all just work. (It will also be a lot faster - you save a whole pointer indirection.)
This is not an analytical answer to the question but a piece of advice with respect to solving (or better circumventing) the problem.
Avoid memory handling on your own if you can. (And it is very likely that you actually can avoid it.)
You can read my answer on the question "1D or 2D array, what's faster?" to get a lengthy explenation why it is probably undesirable to use the kind of memory layout you're using.
Furthermore, you'll find an (yet untested) example of how to implement a simple matrix container on top of std::vector.
You can look at the scheme and try to implement your own if you want. The design has several advantages compared to your implementation:
It is templated and thus usable with int as well as many other types.
Conformance to the standard container concept is achieved easily.
No destructor / copy constructor / move constructor or assignment operators required: std::vector is handling the resources and does the "dirty work" for you.
If you still want to use your RAW-Pointer approach (for academic purposes or something):
Read What is meant by Resource Acquisition is Initialization (RAII)? and try to understand the answers.
Read What is The Rule of Three? properly and make sure you have implemented (preferably obeying the RAII concept) those functions:
copy constructor,
destructor,
assignment operator and if desired
move constructor and
move assignment operator.
Still read my answer to the "1D or 2D array, what's faster?" question to see how you would want to organize your allocations in order to be exception safe in case of std::bad_alloc.
Example: Your constructor the 'a little better' way:
Matrix::Matrix(std::size_t const matr_size) // you have a size here, no sign required
{
Matr = new int*[matr_size];
std::size_t allocs(0U);
try
{ // try block doing further allocations
for (std::size_t i = 0; i < matr_size; ++i)
{
Matr[i] = new int[matr_size]; // allocate
++allocs; // advance counter if no exception occured
for(std::size_t j = 0; j < matr_size; j++)
{
Matr[i][j] = rand() % 100;
}
}
}
catch (std::bad_alloc & be)
{ // if an exception occurs we need to free out memory
for (size_t i = 0; i < allocs; ++i) delete[] Matr[i]; // free all alloced rows
delete[] Matr; // free Matr
throw; // rethrow bad_alloc
}
}

Init a multidimensional-array-pointer ****

I want to store pointers (Bar *) in a multidimensional-array of 2 dimensions. And I want to access to this array from a pointer.
So I want to initialize a **foo[][] (or ****fo).
Bar ****_bars; // declaration
int n, m; // dimensions size
_bars = new Bar ***;
*_bars = new Bar **[n];
for (int i = 0; i < n; i++) {
*_bars[i] = new Bar *[m];
for (int j = 0; j < m; j++) {
*_bars[i][j] = new Bar();
}
}
My app crash at line *_bars[i][j] = new Bar(); when i=0 and j=1.
Your problem is likely the precedence of the [] and * operators (see this answer). For example, in your case the expression *_bars[i] is evaluated like:
*(_bars[i]) = ....
Since there is only one element in _bars[] you run into "issues" with _bars[1]. Same thing with *_bars[i][j].
But really, please use std::array<> or std::vector<> for something like this.

Double (two-dimensional) array using std::unique_ptr

I have a double array allocated by pointer to pointer.
// pointer to pointer
int **x = new int *[5]; // allocation
for (i=0; i<5; i++){
x[i] = new int[2];
}
for (i=0; i<5; i++){ // assignment
for (j=0; j<2; j++){
x[i][j] = i+j;
}
}
for (i=0; i<5; i++) // deallocation
delete x[i];
delete x;
I am trying to do this using unique_ptr:
std::unique_ptr<std::unique_ptr<int>[]> a(new std::unique_ptr<int>[5]);
for (i=0; i<5; i++)
a[i] = new int[2];
but kept getting an error saying that no operator = matches these operands. What I am doing wrong here?
You cannot assign a int* to a std::unique_ptr<int[]>, that is the cause for your error. The correct code is
a[i] = std::unique_ptr<int[]>(new int[2]);
However, piokuc is correct, that it is highly unusual to use unique_ptr for arrays, as that's what std::vector and std::array are for, depending on if the size is known ahead of time.
//make a 5x2 dynamic jagged array, 100% resizable any time
std::vector<std::vector<int>> container1(5, std::vector<int>(2));
//make a 5x2 dynamic rectangular array, can resize the 5 but not the 2
std::vector<std::array<int, 2>> container1(5);
//make a 5x2 automatic array, can't resize the 2 or 5 but is _really fast_.
std::array<std::array<int, 2>, 5> container;
All of these can be initialized and used just the same as the code you already had, except they're easier to construct, and you don't have to destroy them.
If you do not have the luxury of using a std::array or a std::vector instead of a dynamically allocated array, you can use a std::unique_ptr for a two-dimensional array in C++11 as follows:
std::unique_ptr<int*, std::function<void(int**)>> x(
new int*[10](),
[](int** x) {
std::for_each(x, x + 10, std::default_delete<int[]>());
delete[] x;
}
);
The unique_ptr declaration takes care of allocating the row dimension of the array. The trailing () in new int*[10]() ensures that each column pointer is initialized to nullptr.
A for loop then allocates the column arrays:
for (size_t row = 0; row < 10; ++row) {
(x.get())[row] = new int[5];
}
When the unique_ptr goes out of scope, its custom deleter lambda function takes care of deleting the column arrays before deleting the row array. The for_each expression uses the default_delete functor.
for (i=0; i<5; i++) // deallocation
delete x[i];
delete x;
NO NO NO NO
delete [] x[i];
delete [] x;
// yo
The only reasons I can think of to use std::unique_ptr (or say boost::scoped_array) over std::vector for holding arrays are usually not applicable...
1) it saves 1 or 2 pointers worth of memory, depending on if you know what the size of all the arrays is [irrelevant unless you have a massive number of very small arrays]
2) in case you are just passing the array into some function that expects a C style array or raw pointer, it may feel like a more natural fit. std::vector IS guaranteed to be on sequential storage though, so passing (a.empty() ? nullptr : &a[0], a.size()) into such a function is 100% legit as well.
3) standard containers in MSVC debug mode are "checked" by default and very slow, which might be annoying when doing scientific programming on large datasets.
Your code is effectively manipulating an array of arrays of int.
In C++ you would normally want to implement it as:
std::vector<std::vector<int> > x;
This is not a good case for unique_ptr. Also, you should not need to use pointers to unique_ptr and allocate unique_ptr objects dynamically. The whole point of unique_ptr is to eliminate usage of pointers and to provide automatic allocation and deallocation of objects.
#include <iostream>
#include <memory>
#define print(x) std::cout << x
#define println(x) std::cout << x << std::endl
int main() {
std::unique_ptr<std::unique_ptr<int[]>[]> arr(new std::unique_ptr<int[]>[2]());
for (int i = 0; i < 2; i++)
{
arr[i] = std::make_unique<int[]>(5);
for (int j = 0; j < 5; j++) {
arr[i][j] = j;
println(arr[i][j]);
}
println(arr[i]);
}
}
An example further up inspired me for this solution
size_t k = 10;
std::unique_ptr<int*, std::function<void(int**)>> y(new int*[k](),
[](int** x) {delete [] &(x[0][0]);
delete[] x;});
// Allocate the large array
y.get()[0] = new int[k*10];
// Establish row-pointers
for (size_t row = 0; row < k; ++row) {
(y.get())[row] = &(y.get()[0][0]);
}
Here all dimensions can be dynamic and you can wrap it inside a class and expose an operator[]. Also the memory is allocated in a contiguous manner and you can easily introduce an allocator, which allocates aligned memory.
for (i=0; i<5; i++) // deallocation
delete x[i];
delete x;
It is a common mistake here.
x[i] is an array so you have to delete each array first using delete[]
Then you can delete you array of int* by using delete[]
Correct desallocation would be:
for (i=0; i<5; i++)
delete[] x[i]; //desallocate each array of int
delete[] x; //desallocate your array of int*
x = nullptr; //good practice to be sure it wont cause any dmg

Invalid Allocation Size (in derived class copy constructor)

I have narrowed down my issue to a derived classes copy constructor, but I am unsure of the cause.
EDIT: M, N and Data are Private. The error I recieve is 'Invalid allocation size: 4294967295 bytes' - which I understand is caused when passing a -1 to new. I'm unsure why this would occur unless the data is lost when the class comunicate.
BinaryMatrix::BinaryMatrix(const BinaryMatrix& copy) : Matrix(copy)
{
//cout << "Copy Constructor\n";
M = copy.M;
N = copy.N;
data = new double[M*N]; //This line causes the allocation error
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
data[i*N+j] = copy.data[i*N+j];
}
}
}
The above is my derived copy constructor which causes the error. I have marked the allocation line.
I can only assume that M and N are not being read correctly. Though I am unsure why. I'll include both derived and base constructors, and the base copy as well.
Thanks for any assistance.
MATRIX (BASE) CONSTRUCTOR
Matrix::Matrix(int M, int N, double* input_data)
{
this->M = M;
this->N = N;
//cout << "Matrix Constructor\n";
data = new double[M*N];
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
data[i*N+j] = input_data[i*N+j];
}
}
delete [] input_data;
}
MATRIX (BASE) COPY CONSTRUCTOR
Matrix::Matrix(const Matrix& copy)
{
//cout << "Copy Constructor\n";
M = copy.M;
N = copy.N;
data = new double[M*N];
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
data[i*N+j] = copy.data[i*N+j];
}
}
}
BINARYMATRIX (DERIVED) CONSTRUCTOR
BinaryMatrix::BinaryMatrix(int M, int N, double* input_data) : Matrix(M, N, input_data)
{
data = new double[M*N];
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
this->data[i*N+j] = this->getRead(i, j);
}
}
double thr_val = this->Mean();
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
if (this->data[i*N+j] > thr_val)
this->data[i*N+j] = 1;
if (this->data[i*N+j] < thr_val)
this->data[i*N+j] = 0;
}
}
}
Why do you create a new copy of the matrix data in the BinaryMatrix copy constructor? The copy constructor of Matrix you call from the BinaryMatrix copy constructor already does this.
In the BinaryMatrix copy constructor you discard the copy of the matrix data the Matrix copy constructor already made (without deleteing it) and create a new one. This is a memory leak - the memory will be exhausted if you do that often enough.
If M and N are private to Matrix and BinaryMatrix derives from Matrix, I am not sure why your code compiles (you should not be able to access M, N in BinaryMatrix). If your declaration of BinaryMatrix also includes members M and N (as well as Matrix::N and Matrix::M) then this could be the source of the problem.
If BinaryMatrix does not declare M and N, then I think we still don't have enough data to diagnose your problem. To guess a bit, perhaps M*N does not fit into the type used for M. So you have an arithmetic overflow. The array size is specified in size_t, so a cast will work OK.
Also, you probably want to delegate the management of the data to exactly one of the classes. That is, do either this:
BinaryMatrix::BinaryMatrix(const BinaryMatrix& copy) : Matrix(copy)
{
// M, N, data already set in Matrix::Matrix(const Matrix&)
// The data has also been copied, so there is nothing to do here.
}
or this:
#include <algorithm>
BinaryMatrix::BinaryMatrix(const BinaryMatrix& copy)
: Matrix(), M(0), N(0),
data(0) // null in case new throws an exception (avoid bad delete in dtor).
{
const size_t nelems(size_t(copy.M)*size_t(copy.N));
data = new double[nelems];
M = copy.M;
N = copy.N;
stl::copy(copy.data, copy.data+nelems, data);
}
I think generally it is not a good idea to use int for iterating over dynamic data structures, since nothing guarantees that the actual size of the structure fits into int. That guarantee does exist however for size_t (any existing object must have a size representable in size_t, so you can iterate over any contiguous object using size_t).
In fact, I'm not really sure what distinction (of purpose or behaviour) you're trying to get from Matrix and BinaryMatrix. The data seems to have the same representation. If it is a difference of behaviour but not representation you are looking for, I think it might be better to use composition (that is, a separate un-inherited representation class) rather than inheritance. See What is the Liskov Substitution Principle? for an explanation of how to think usefully about when to use inheritance.
However, if none of the answers you have seen so far actually helps to solve your problem, you should put some time into cutting down your example: what is the smallest complete example program which demonstrates your problem? Post that.
If the error is that M and N are private. then you must change there protection level to protected or public or provide an access method that is. Vairables defined in a base class that are private are innacceassable to the derived classes.
class A
{
int x;
}
class B : public A
{
int DoSomething()
{
return x; //This is an error X is private to class A and as such inaccessible.
}
}

Allocating 2d array of chars

Constructor
This is how I'm allocating it:
char **board = new char*[width];
for(i = 0; i < width; i++){
board[i] = new char[height];
for(j = 0; j < height; j++)
board[i][j] = 0;
}
this->board = &board;
Inside the class, it's:
char ***board;
Destructor:
Now I want to delete it, so I wrote this (the board it the class field):
for(i = 0; i < width; i++)
delete (*board)[i];
delete (*board);
When running this:
Board* b = new Board(16, 30, 99);
delete b;
I get an Unhandled exception. Why?
You are storing a pointer to a variable on the stack, which becomes invalid as soon as the constructor returns. You should declare your class's data member as char **board and assign this->board = board.
EDIT: See also #Kerrek SB's comment. The local variable is redundant. Just use the data member directly (without the this->).
EDIT 2: Rectangular arrays are best created as a single array, using pointer arithmetic to index (which is what the compiler does with declared 2D arrays anyway):
char *board;
...
board = new char[width*height];
for(i = 0; i < width*height; ++i){
board[i] = 0;
}
...
char& operator()(int i, int j) { return board[width*i + j]; }
This has the advantage of requiring just one memory allocation (and therefore one delete[]). It also improves cache locality because the cells are contiguous.
Even better, if you know the dimensions at compile-time, use templates:
template <int W, int H>
class Board {
char board[W][H];
...
};
...
Board<8, 8>* b = new Board<8, 8>(...);
This requires no memory allocation at all (other than the new Board, of course).
Anything that you new you need to delete, in the exact same way:
board = new char*[width];
...
board[i] = new char[height];
...
...
delete[] board[i];
delete[] board;
No dereferencing is needed in this case.
You should use the powers of C++.
class Board
{
std::vector<std::vector<char>> board;
public:
Board(std::vector<std::vector<char>> const& board) : board(board) {}
Board(size_t x, size_t y, char val = 0)
{
std::vector<char> x2(x, val);
this->board(y, x2);
}
};
All you've got to do now is board[y].push_back(char_x_val) in order to append a new element to the end. You can treat board[y][x] just like any other 2D array (well, almost), but not worry about the deallocation.
Read up more on vectors here. (Anyone know a good tutorial?)