In code:
template<class T,int row, int col>
void invert(T (&a)[row][col])
{
T* columns = new T[col * row];
T* const free_me = columns;
T** addresses = new T*[col * row];
T** const free_me_1 = addresses;
/*cpy addresses*/
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < col; ++j)
{
*addresses = &a[i][j];
++addresses;
}
}
addresses = free_me_1;
/*cpy every column*/
for (int i = 0; i < col; ++i)
{
for (int j = 0; j < row; ++j)
{
*columns = a[j][i];
++columns;
}
}
columns = free_me;
/*cpy from columns to addresses*/
for (int i = 0; i < (col * row); ++i)
{
*addresses[i] = columns[i];
}
delete[] free_me_1;
delete[] free_me;
}
I've observed that while iterating, value of variable columns equals zero and I think thats the problem.
Thanks for your help.
P.S. I've pasted final version of this fnc. It works as intended now. Thank you everyone for your valuable help.
You write past the buffer end because the buffer is too small.
T* columns = new T[col];
should be
T* columns = new T[col*row];
Writine past the buffer end is undefined behavior - in your case it's heap corruption because you overwrite some service data essential for the heap functioning and so delete[] fails.
You initialize columns as a new T[col]. Then you increment columns in the inner loop, which gets execute col*row times - unless rows==1, you increment columns past the end of the array you've allocated, causing undefined behaviour.
Note that even once you fix that, your function is still very wrong - it has neither a return value nor side effects. It should be a no-op. It definitely doesn't invert its parameter.
Related
I am currently learning how to utilize raw pointers in C++. I understand how to dynamically allocate a 2D array, however, as an exercise for myself, I attempted to apply my understanding of multiple levels of indirection to allocate a 3D array. My attempt is presented below:
int main() {
double*** matrix { new double**[10] {} };
for (size_t i {}; i < 10; ++i) {
matrix[i] = new double*[i + 1] {};
for(size_t j {}; j < 10; ++j) {
matrix[i][j] = new double[i + 1] {};
}
}
std::cout << matrix[0][0][0] << std::endl;
for (size_t i {}; i < 10; ++i) {
for (size_t j {}; j < 10; ++j) {
delete[] matrix[i][j];
matrix[i][j] = nullptr;
}
delete[] matrix[i];
matrix[i] = nullptr;
}
delete[] matrix;
matrix = nullptr;
return 0;
}
Since I'm using uniform initialization, matrix[0][0][0] should print the value 0.0; However, I'm getting a garbage value when doing so. Furthermore, I have a double free or corruption (out) error, which I assume is telling me that I am attempting to free memory from the same address twice.
Any help or guidance would be appreciated. I'm just trying to fully understand raw pointers.
Edit: I understand that double*** is not actually a 3D array. I'm just trying to utilize simple terminology.
matrix[i] = new double*[i + 1] {};
for(size_t j {}; j < 10; ++j) {
This is your error right here, you allocate an array of 'i + 1' element and then loop for 10, you either need to have i + 1 in both places or 10 otherwise this is undefined behavior. The same applies for deletion (the loop checks for 10 but you only allocated i + 1).
So for a project I have i need to create a function to 'Resize' the first dimension of a dynamically allocated 3d array of shorts, the function cant alter the original data and must only alter the first dimension of the array.
3darray[alter this][stays the same][stays the same]
The variables passed into the function are the pointer that points to the 3d array, the old size, and the new size.
Ive tried this:
void reallocShort3d(short ***&ptr, size_t oldSize, size_t newSize)
{
short *** temp;
temp = (short***) realloc(ptr,(newSize - oldSize) * sizeof(ptr));
ptr = temp;
}
but it does not seem to be working, any idea on where i went wrong and possible solutions?
Thanks
EDIT: I realise that I can't use realloc now as th 3d array was created with new, we are only given the old and new sizes of the first dimension and the array itself, we are not allowed to use vectors:
/**
* #brief reallocates/resizes a 3D array of shorts to fit into a new size.
* Size here refers to the first dimension. i.e. ptr[size][row][col].
*
* #note after the function executed, the original data in the array must
* not be altered in any way. That is to say, only the first dimension of
* ptr may be altered.
*
* #NOTE! this function must work in general
*
* #param ptr is the pointer that refers to the 3D array to be resized.
* #param oldSize is the current total number of elements in the first
* dimension of ptr. e.g. ptr[this amount here][row][col]
* #param newSize is the new size that ptr will have after the function
* has been executed. ptr[the new amount here][row][col]
*/
SECOND EDIT:
Heres the code used to allocate the 3d array:
ptr = new short**[2];
for (int i = 0; i < 2; i++)
{
ptr[i] = new short*[12];
for (int j = 0; j < 12; ++j)
{
ptr[i][j] = new short[numDaysinMonth(j)];
}
}
Given the way OP's code allocates the memory, a simple way to resize it is:
short ***tmp;
// in OP's code rows = 12 while the inner dimension is the number of days in a month
// so we can use cols = 31
tmp = new short**[newSize];
// copy the old data
for ( size_t i = 0; i < oldSize; ++i ) {
tmp[i] = ptr[i];
}
// allocate memory for the new data
for ( size_t i = oldSize; i < newSize; ++i ) {
tmp[i] = new short*[rows];
for ( size_t j = 0; j < rows; ++j ) {
tmp[i][j] = new short[cols];
}
}
delete[] ptr;
ptr = tmp;
EDIT
The comment of #PaulMcKenzie points out a major flaw in this code. In C++, operator new throws an exception when it's unable to allocate the requested memory. If this happens, our options are limited and in most cases the only thing we can do is some clean up and exit the program.
In the following snippet I'll try to rewrite the function with OP's signature (which I personally, don't like) and to avoid the possible memory leaks. This function eventually rethrows a std::bad_alloc exception and it is up to the caller to deal with it (which, I'm pretty much sure, OP's code doesn't).
I'd like to remark that a far better practice would be to stick to the Standard Library containers and/or encapsulate all the memory managment in a class, to ensure RAII.
void reallocShort3d(short ***&ptr, size_t oldSize, size_t newSize, size_t rows, size_t cols ) {
short ***tmp = nullptr;
std::bad_alloc ee;
try {
tmp = new short**[newSize];
size_t i = 0, j = 0, ii, jj, kk;
for ( ; i < oldSize; ++i ) {
tmp[i] = ptr[i];
}
for ( ; i < newSize; ++i ) {
try {
tmp[i] = new short*[rows];
for ( j = 0; j < rows; ++j ) {
try {
tmp[i][j] = new short[cols];
}
catch ( const std::bad_alloc &e ) {
for ( jj = 0; jj < j; ++jj ) {
delete[] tmp[i][jj];
}
delete[] tmp[i];
throw e;
}
}
}
catch ( const std::bad_alloc &e ) {
for (ii = oldSize; ii < i; ++ii) {
for ( jj = 0; jj < rows; ++jj ) {
delete[] tmp[ii][jj];
}
delete[] tmp[ii];
}
delete[] tmp;
throw e;
}
}
delete[] ptr;
ptr = tmp;
}
catch ( const std::bad_alloc &e ) {
std::cout << "Error: unable to reallocate.\n";
throw e;
}
}
As alluded to in the comments, the signature of the reallocate function is not sufficient for the general case as one requires knowledge of the rows, cols and slices of the original 3D array to be able to perform reallocation.
So, assuming you can fix the method signature for the general case the following is a possible solution:
void reallocate_short_3d_arr(short***& ptr, std::size_t new_rows, std::size_t old_rows,
std::size_t cols, std::size_t slices) {
// allocate memory for tmp 3d arr
short*** tmp = new short**[new_rows];
for (std::size_t i = 0; i < new_rows; ++i) {
tmp[i] = new short*[cols];
for (std::size_t j = 0; j < cols; ++j)
tmp[i][j] = new short[slices];
}
// select correct rows for contraction or expansion of ptr
std::size_t tmp_rows = (new_rows > old_rows) ? old_rows : new_rows;
// copy all entries from ptr to tmp
for (std::size_t i = 0; i < tmp_rows; ++i) {
for (std::size_t j = 0; j < cols; ++j) {
for (std::size_t k = 0; k < slices; ++k)
tmp[i][j][k] = ptr[i][j][k];
}
}
// delete original ptr memory
for (std::size_t i = 0; i < old_rows; ++i) {
for (std::size_t j = 0; j < cols; ++j) {
delete[] ptr[i][j];
}
delete[] ptr[i];
}
delete[] ptr;
// assign ptr to tmp such that ptr points to reallocated memory
ptr = tmp;
}
One could probably optimise this via using std::move to assign the contents of ptr to tmp instead fairly trivially as the original ptr contents is deleted afterwards anyway so it is safe to move it.
Of course, this is all very silly C++ though and could be easily achieved via std::vector as follows:
std::vector<std::vector<std::vector<short>>> vec_3d(rows,
std::vector<std::vector<short>>(cols,
std::vector<short>(slices))); // initialise "3D vector" of dims rows*cols*slices
vec_3d.resize(new_rows); // resize just the rows, leaving slices and columns the same
My class assignment is to create a program using OOP that creates a dynamic array that can act like a vector. My remove entry function is crashing when I run it. After messing around with it for a while I can't seem to make it stop crashing no matter what I do. Here are the instructions for this function in particular.
The function should search dynamicArray for the string.If not found, it returns false. If found, it creates a new dynamic array one element smaller than dynamicArray. It should copy all elements except the input string into the new array, delete dynamicArray, decrement size, and return true.
bool dynamicStringArray::deleteEntry(std::string oldString)
{
for (int i = 0; i < size; i++){
if (dynamicArray[i].compare(oldString) == 0){
std::string* shortArray = new std::string[size - 1];
delete &dynamicArray[i];
for (int j = 0; j < size - 1; j++)
shortArray[j] = dynamicArray[j];
size--;
for (int j = 0; j < size; j++)
dynamicArray[j] = shortArray[j];
return 1;
}
}
return 0;
}
You have a bit of misunderstanding about what
delete &dynamicArray[i];
does.
It does not remove the i-th entry from dynamicArray. It tries to deallocate memory of one objet -- the i-th object. That in itself is cause for undefined behavior.
You may not call delete on a pointer unless it was returned by a call to new.
The second problems is that dynamicArray continues to have that pointer as the i-th element.
Here's an updated if statement that should work.
if (dynamicArray[i].compare(oldString) == 0) {
std::string* shortArray = new std::string[size - 1];
// Copy everything form dynamicArray to shortArray except
// the i-th element.
for (int j = 0; j < i; j++)
{
shortArray[j] = dynamicArray[j];
}
for (int j = i+1; j < size; j++)
{
shortArray[j-1] = dynamicArray[j];
}
// Delete old array
delete dynamicArray;
// Make the newly allocated array the array of
// the object.
dynamicArray = shortArray;
// Decrement the size
--size;
return 1;
}
I am new in C++ programing so I need a help about 2D arrays. Is it possible to create complex array from two real array with two for loops?I was trying to do that in my code but...I do not know how to do that.
Thanks for help!
This is my code::
#include <iostream>
#include <fstream>
#include <complex>
#include <cmath>
using namespace std;
int const BrGr = 15, BrCv = BrGr + 1, BrSat = 24;
//(BrCv=number of nodes,BrSat=number of hours)
int main()
{
// Every array must be dynamic array.It is a task.Is this correct way?
auto *Ipot = new double[BrCv - 1][BrSat];
auto *cosfi = new double[BrCv - 1][BrSat];
auto *S_pot = new complex<double>[BrCv - 1][BrSat];
auto *I_inj = new complex<double>[BrCv - 1][BrSat];
auto *V_cvo = new complex<double>[BrCv][BrSat];
ifstream reader("Input.txt");
if (reader.is_open())
{
for (int i = 0;i < BrCv - 1;i++)
{
for (int j = 0;j < BrSat;j++)
{
reader >> Ipot[i][j];
}
}
for (int i = 0;i < BrCv - 1;i++)
{
for (int j = 0;j < BrSat;j++)
{
reader >> cosfi[i][j];
}
}
}
else cout << "Error!" << endl;
reader.close();
// Here i want to create 2D array of complex numbers - Is this correct way?
// Also in same proces i want to calculate a value of S_pot in every node for every hour
for (int i = 0;i < BrCv - 1;i++)
{
for (int j = 0;j < BrSat;j++)
{
S_pot[i][j] = complex<double>(Ipot[i][j]*cosfi[i][j],Ipot[i][j]*sqr(1-pow(cosfi[i][j],2)));
}
}
// Here i give a value for V_cvo in nodes for every single hour
for (int i = 0;i < BrCv;i++)
{
for (int j = 0;j < BrSat;j++)
{
V_cvo[i][j] = 1;
}
}
// Here i want to calculate a value of I_inj in every node for every hour
for (int i = 0;i < BrCv - 1;i++)
{
for (int j = 0;j < BrSat;j++)
{
I_inj[i][j] = conj(S_pot[i][j] / V_cvo[i][j]);
}
}
// Here i want to delete all arrays
delete[] Ipot, cosfi, S_pot, I_inj, V_cvo;
system("pause");
return 0;
Note: I'm using double through out these examples, but you can replace double with any type.
To be honest, you probably don't want to use a 2D array.
Creating a 2D dynamically-sized array in C++ is a multi-stage operation. You can't just
double twoDArray [nrRows][nrColumns];
or
auto twoDArray = new double[nrRows][nrColumns];
There are a couple things wrong with this, but the most important is the rows and columns are not a constant, defined at compile time values. Some compilers allow the first, but this cannot be guaranteed. I don't know if any compiler allows the second.
Instead, First you create an array of rows to hold the columns, then you separately create each row of columns. Yuck.
Here's the set up:
double * arr[] = new double*[nrRows]; // create rows to point at columns
for (size_t index = 0; index < nrRows; index++)
{
arr[index] = new double[nrColumns]; // create columns
}
And here's clean-up
for (size_t index = 0; index < nrRows; index++)
{
delete[] arr[index]; // delete all columns
}
delete[] arr; // delete rows
For your efforts you get crappy spacial locality and the performance hit (Cache miss) that causes because your many arrays could be anywhere in RAM, and you get crappy memory management issues. One screw-up, one unexpected exception and you have a memory leak.
This next option has better locality because there is one big data array to read from instead of many, but still the same leakage problems.
double * arr2[] = new double*[nrRows]; // create rows to point at columns
double holder[] = new double[nrRows* nrColumns]; // create all columns at once
for (size_t index = 0; index < nrRows; index++)
{
arr[index] = &holder[index * nrColumns]; // attach columns to rows
}
and clean up:
delete[] arr2;
delete[] holder;
In C++, the sane person chooses std::vector over a dynamically-sized array unless given very, very compelling reason not to. Why has been documented to death all over SO and the Internet at large, and the proof litters the Internet with hijacked computers serving up heaping dollops of spam and other nastiness.
std::vector<std::vector<double>> vec(nrRows, std::vector<double>(nrColumns));
Usage is exactly what array users are used to:
vec[i][j] = somevalue;
This has effectively no memory problems, but is back to crappy locality because the vectors could be anywhere.
But...!
There is a better method still: Use a One Dimensional array and wrap it in a simple class to make it look 2D.
template <class TYPE>
class TwoDee
{
private:
size_t mNrRows;
size_t mNrColumns;
vector<TYPE> vec;
public:
TwoDee(size_t nrRows, size_t nrColumns):
mNrRows(nrRows), mNrColumns(nrColumns), vec(mNrRows*mNrColumns)
{
}
TYPE & operator()(size_t row, size_t column)
{
return vec[row* mNrColumns + column];
}
TYPE operator()(size_t row, size_t column) const
{
return vec[row* mNrColumns + column];
}
};
This little beastie will do most of what you need a 2D vector to do. You can copy it, you can move it. You can crunch all you want. Jay Leno will make more.
I jumped directly to the templated version because I'm stumped for a good reason to explain class TwoDee twice.
The constructor is simple. You give it the dimensions of the array and it builds a nice, safe 1D vector. No muss, no fuss, and No Zayn required.
The operator() functions take the row and column indices, do a simple bit of arithmetic to turn the indices into a single index and then either return a reference to the indexed value to allow modification or a copy of the indexed value for the constant case.
If you're feeling like you need extra safety, add in range checking.
TYPE & operator()(size_t row, size_t column)
{
if (row < mNrRows && column < mNrColumns)
{
return vec[row* mNrColumns + column];
}
throw std::out_of_range("Bad indices");
}
OK. How does the OP use this?
TwoDee<complex<double>> spot(BrCv - 1, BrSat);
Created and ready to go. And to load it up:
for (int i = 0;i < BrCv - 1;i++)
{
for (int j = 0;j < BrSat;j++)
{
Spot(i,j) = complex<double>(7.8*Ipot(i,j),2.3*cosfi(i,j));
}
}
Declaring a dynamic 2D array for a premitive type is the same as for std::complex<T>.
Jagged array:
complex<int> **ary = new complex<int>*[sizeY];
//run loop to initialize
for (int i = 0; i < sizeY; ++i)
{
ary[i] = new complex<int>[sizeX];
}
//clean up (you could wrap this in a class and write this in its destructor)
for (int i = 0; i < sizeY; ++i)
{
delete[] ary[i];
}
delete[] ary;
//access with
ary[i][j];
//assign index with
ary[i][j] = complex<int>(int,int);
It's a little heavier weight than it needs to be, and it allocates more blocks than you need.
Multidimensional arrays only need one block of memory, they don't need one block per row.
Rectangular array:
complex<int> *ary = new complex<int>[sizeX * sizeY];
//access with:
ary[y*sizeX + x]
//assign with
ary[y*sizeX+x] = complex<int>(int,int);
//clean up
delete[] ary;
Allocating just a single contiguous block is the way to go (less impact on allocator, better locality, etc But you have to sacrifice clean and nice subscripting.
I'm tryining overload operator ~ that transpose a given matrix:
Here's my code:
virtual B operator~()const
{
B a(column,row);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<column; j++)
{
a.e[i] = e[j];
}
}
return a;
}
e is pointer to the memory storing all integer elements of B
int *const e;
But on the output I've gotten a matrix filled by zeros and with the same size. I mean if I wnat transpose 5x2, I got the same 5x2 filled by zeros.
Edit:
My constuctor:
B(int r, int c)
: row(r), column(c), e(new int[r*c])
{
for (int i = 0; i < r*c; i++)
{
e[i] = 0;
}
}
Your code is not filling a.e properly: rather than transposing the matrix, it keeps overriding a region that corresponds to the same row with numbers for different columns.
Assuming row-major order, the code should be like this:
for (int i = 0; i<row; i++)
{
for (int j = 0; j<column; j++)
{
a.e[j*row+i] = e[i*column+j];
}
}
Since you mention that you've got a result filled with zeros, the logic of your copy constructor and / or the assignment operator may not be coded correctly. Note that since B::e is allocated dynamically, you need a destructor as well.
B a(column,row);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<column; j++)
{
a.e[i] = e[j];
}
}
Isn't accessing most of the elements in either this or a. Only element 0 to column and 0 to row respectively are accessed.
The zeroing constructor does not reveal how the row/columns are stored, but a guess would be
int& B::at(int r, int c){
return e[r*column + c];
}
The alternative is
return e[c*row + r];
In this case you can transpose by
virtual B operator~()const
{
B a(column,row);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<column; j++)
{
a.at(i, j) = at(j, i); // swap row, column
}
}
return a;
}
First, you seem to always set the first [0..row] elements in the transpose, with the last elements on every row in the original and stop there.
Second, i don't know how B is internally laid, but because you can specify the size of the matrix, i deduce that the internal array that is used to store the elements is allocated dynamically in a one-dimension buffer. This means that you have a copy constructor to avoid problems with the deletion of a at the end of the method. You getting a lot of 0s possibly means (beside the fact that you don't scan the entire matrix), that your copy constructor is not properly implemented.
EDIT Seeing your edit of the question, i tend to be sure that the copy constructor is the problem. You don't have a crash because 5x2 = 2x5 elements (so the internal buffer is the same size).