IntArray::IntArray (int *array, int sz)
{
_size = sz;
int ia = new int[_size];
for (int ix=0; ix<_size; ++ix)
ia[ix] = array[ix];
}
Hello, I'm currently studying C++ for beginners by Stanley Lipmann and I'm going through creating of abstract arrays with Classes help. Can someone explain me what does this code do? By my guess it assigns "sz" value (from outside of class) to "_size", then we create the "ia" dynamic array and after all it assigns values from "array" pointer (that outside of class) to an "ia" array. Thanks :D
That cannot be the full code, where is _size defined? Is it a class member? The leading underscore suggests that. I presume that ia is also a class member of type int *.
What it does is to copy the value of sz into the (presumably) member variable _size. Then it allocates a new array of int. The for loop then copies the elements from the given array into the new memory allocated. Looking at the name it will tell you that this is a constructor. It constructs a new array of ints by copying the given array.
And by the way, indent your code such that it is easier to read, that will make understanding it easier!
IntArray::IntArray(int *array, int sz) {
_size = sz;
ia = new int[_size];
for (int ix = 0; ix < _size; ++ix)
ia[ix] = array[ix];
}
You can use the amazing clang-format for all your formatting needs.
You can throw in a const to the array and sz parameters, that way you can also create new IntArray instances from constant arrays.
Related
I only found solutions for 1d arrays, but couldn't apply them to 2d arrays.
The possible solutions included "vectors", "templates", and "pointers to arrays".
I know I can get vectors to work, but I would rather use either of the other 2. Preferably templates because I don't want to manually destruct, but pointers work too. (the pointer would be pointed to an array created in the constructor).
The class contains an empty 2d array called screen. The constructor is supposed to set its size. I tried too many things for me to list them all here, but I'll show what I currently have. (last thing i tried were pointers to arrays created in the constructor. in this case screen was a char pointer)
Screen::Screen(const int w, const int h) : screen(new char[h][w]) {} {
width = w;
height = h;
}
array size in new-expression must be constant
I failed implementing either of those strategies and received many kinds of errors while trying to make it work. How would I solve this problem? (primarily I want to know how to do this with templates. if not possible then with pointers to arrays created in the constructor)
The question was a little ambiguous, but it sounds like you want to dynamically allocate an array given some input.
Edit I changed the answer to match the code you provided. This creates a 2d array of chars given the height and width.
class Screen {
private:
char **data;
int rows;
int columns;
public:
Screen(int num_rows, int num_cols);
};
Screen::Screen(int num_rows, int num_cols) {
data = new char * [num_rows];
for (int i = 0; i < num_rows; ++i) {
data[i] = new char[num_cols];
}
rows = num_rows;
columns = num_cols;
}
This creates an empty 2D array of chars.
Explanation: All arrays in c are just pointers to the first block in memory of the type you have declared. By having the member variable as double pointer, you have an array of char pointers, which each point to the first value in each of their respective arrays.
BUT be careful, you WILL need to free the data variable to avoid memory leaks, by declaring a destructor.
Screen::~Screen() {
for (int i = 0; i < rows; ++i) {
delete[] data[i];
}
delete[] data;
}
#include < vector >
using namespace std;
class Rclass
{
public:
vector<int> ir0T;
vector<int> ir1T;
private:
int f();
}
int Rclass::f()
{
ir0T.clear();
ir1T.clear();
ir0T.push_back(1);
ir1T.push_back(2);
}
this throws error
"Rclass.cpp:90: error: member function 'clear' not viable: 'this' argument has type 'const vector', but function is not marked const
ir0T.clear();
^~~~"
Rclass.cpp:91: error: member function 'clear' not viable: 'this' argument has type 'const vector', but function is not marked const
ir1T.clear();"
why?
^~~~
I tried adding "const vector ir0T;"
You cannot set the matrix member variable to a local varable created in a local member function - the local variable will be destroyed when the function ends and then the matrix member variable won't be pointing to anything. So instead, if you insist on using a raw pointer, use calloc() because it allocates the memory like malloc and then it sets it all to zero. The main problem with this is that then you need a copy constructor, assignment operator and destructor - That's not the way to go if you can help it. It would be better to use a std::vector<std::vector<int>> because all the dynamic allocation and deallocation is hidden from you. Plus you can reserve the size if you know it ahead of time. How to initializ the "vector"-ized version to zero can be seen here: Initializing a two dimensional std::vector
#include <vector>
class CS
{
private:
std::vector<std::vector<int> > Rightalpha;
public:
void CreateMtrx(int a, int b)
{
// Defaults to zero initial value
Rightalpha = std::vector<std::vector<int> >(a, std::vector<int>(b));
}
};
int main()
{
CS cs;
cs.CreateMtrx(4,4);
return 0;
};
A better alternative if it is fixed and you know ahead of time how big the matrix is: you can just use a plain array directly as a member variable instead of using a pointers to dynamically allocated memory. If the matrix is small (like 4x4) this will give you cache locality and a performance improvement. Plus if you are using c++11 you can clear the array at the declaration and you don't need a CreateMatrix() member variable at all - something like this:
class CS
{
private:
int Rightalpha[4][4] = {};
};
int main()
{
CS cs;
return 0;
};
Or like one of the comments suggested you could use std::array instead of a plain array, if you want a nice STL-like interface to the array. There are some advantages listed here: Replace fixed size arrays with std::array?
Firstly a few fundamentals.
When CreateMtrx() returns Rightalpha will become invalid as a will destruct.
And I would recommend using lower camel case naming for variables and upper camel case for types. i.e. rightAlpha instead of Rightalpha, to avoid confusion with types.
As for your actual question you can initialise a 2D array with a nested loop:
for(unsigned int i = 0; i < 4; i++)
{
for(unsigned int j = 0; j < 4; j++)
{
rightAlpha[i][j] = 0;
}
}
Finally, when asking for help 'craps up' is not conducive to constructive answers. It is important to be clear on what your expected behaviour is and what results you are actually seeing.
If Rightalpha is a data member of your class it doesn't need to be an int**. You probably just want it to be an int[4][4] and skip using a local variable 'a' in your create function.
If you really want it to be a pointer, just make it an int*, and use it with 2D-array syntax. Instead of: int a[4][4]; Do: int* a = new [4*4];
I see from the comment that you can't change the type of Rightalpha. You will then need to do manual memory management. You will need to initialize you int** with the new operator.
You will need to allocate each array in the 2D array.
rightAlpha = new int*[4];
for (int i = 0 ; i < 4 ; i++) {
rightAlpha[i] = new int[4];
}
You can read more about initialisation of a multi-dimentional arrays here:
How do I declare a 2d array in C++ using new?
Even if that works, you will need to free and manage memory and deal carefully with all the pitfalls of manual memory management. That's why I strongly suggest to use a std::vector<int>:
struct CS {
createMatrix() {
rightAlpha = std::vector<int>(4*4);
}
private:
std::vector<int> rightAlpha;
With this solution, you don't need to worry about memory stuff as the std::vector will do it for you.
If you need matrix semantics, you can add a function that returns the right element according to a j i position.
int operator()(int i, int j) const {
return rightAlpha[j+4*i];
}
It may be used like this:
CS myCs;
myCs(3, 2);
I was wondering if this is the proper way create a temporary array using pointers in a class. Part of my problem says this:
getMedian – returns the median value of the array. See Chapter 10 Programming Challenge 6 (p. 693) for a discussion of the term median. Taking the median will require a sorted array. You will need to create a temporary array to sort the values (to preserve the ordering of numbers). Do not sort the private member numbers array. Dynamically allocate/deallocate a temporary array in your getMedian function to determine the median.
My code:
double Statistics::getMedian() const
{
int tempArray[length];
for (int k = 0; k < length; k++){
tempArray[k] = numbers[k];
}
bubbleSort(tempArray);
return 0;
}
Before obviously doing the median part and a proper return statement, is this.
How you properly copy over a temporary array to alter for this problem? I don't think it is because I'm not properly allocating or deallocating anything, but I don't understand how to create a temporary array without altering the original.
Your assignment says you are to allocate/deallocate the array dynamically. That means (in C++) using new and delete. Since you want an array, you should use array space allocator operators new[] and delete[].
double Statistics::getMedian() const
{
int *tempArray = new int[length];
for (int k = 0; k < length; k++){
tempArray[k] = numbers[k];
}
// work with tempArray
delete[] tempArray;
return 0; // or the median
}
EDIT:
As suggested in the comment below, modern (C++11 and newer) way is to use smart pointers. That would mean your code could look like this.
#include <memory>
double Statistics::getMedian() const
{
std::unique_ptr<int[]> tempArray (new int[length]);
for (int k = 0; k < length; k++){
tempArray[k] = numbers[k];
}
// work with tempArray like you would with an old pointer
return 0; // or the median
// no delete[], the array will deallocate automatically
}
Check unique_ptr template class for more details. Note that this solution might not be what your professor wants, especially when the assignment talks about deallocation.
I want to have an array accessible by all functions of a class.
I put the array as private variable in the header file.
private:
int* arrayName;
In the .cpp file where I implement the class, the constructor takes in an int value (size) and creates the array. The goal is to fill it up
ClassName::ClassName(int numElements){
arrayName = new int[numElements]; //make arrays the size of numElements
for(int i = 0; i<numElements; i++)
arrayName[i] = 0;
}
I feel like this is quite inefficient. I know you can do int array[5] = {0}; but how do you do it when you don't initially know the size.
If you want to zero-initialize a newed array, just do value-initialize it. This has the effect of zero-initializing its elements:
arrayName = new int[numElements]();
// ^^
But you really want to be using an std::vector<int>.
private:
std::vector<int> vname;
and
ClassName::ClassName(int numElements) : vname(numElements) {}
This way you don't have to worry about deleting an array and implementing copy constructors and assignment operators.
You can use the memset function:
memset(arrayName,0,sizeof(int)*numElements);
This void * memset ( void * ptr, int value, size_t num ); function sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char).
To use it you must include the string.h header file.
For more information: http://www.cplusplus.com/reference/cstring/memset/
What you want to do is progressively expand the array on demand.
arrayName = new int[numElements];
for(int i = 0; i<numElements; i++)
arrayName[i] = 0;
The above code (what you gave) will give you an array of size numElements, and THEN the for loop will fill it. This is allocated now, and can't, as I understand it, be simply or easily resized (memset will overwrite previously held values in the array).
You could copy the whole array over every time you want to resize it:
int * oldarr = new int[OldSize];
//fill your old array
int * newarr = new int[NewSize];
for(int i = 0; i<OldSize; i++)
newarr[i] = oldarr[i];
Other than that, you could make the array much larger, or you could use various STLs, such as std::vector. Vector can be increased with a simple push_back function, and allows [] operator access (like arr[5] and whatnot).
Hope this helps!
Here we are once again good people of the internet.
This is the code I'm using:
//This is what is in the header file
int *myArr[]; // A two-dimensional array representing holding the matrix data
//This is what is in the definition file
Matrix::Matrix(int n, int m)
{
myRows = n;
myColumns = m;
initialize();
}
void Matrix::initialize()
{
*myArr = new int[myRows];
for (int i=0; i < 3; i++)//Only set to 3 since myRows is acting crazy
{
myArr[i] = new int[myColumns];
}
}
For some reason when I use myRows variable to create the myArr array it just seems to stop referencing the value it was pointing towards before.
For instance I give it the value 3 and after the *myArr = new int[myRows] has been executed it changes the value of myRows to 9834496, which I don't understand.
Does the "new" de-reference the variable or something?
Or am I doing something wrong?
Oh and since this is a school practice project (so I won't blame you if you don't answer) I would prefer an answer over working code, so that I could know what I did wrong for future projects.
int *myArr[];
This is wrong! You've to tell the compiler the size also, of your array of pointer. How about if you declare int a[]. You're telling the compiler to create an array of int, of unknown size, which is not allowed in C++. That is why you cannot do that.
I would suggest you to do this:
int **myArr;
void Matrix::initialize()
{
myArr = new int*[myRows]; //note int* here!
for (int i=0; i < myRows; i++)
{
myArr[i] = new int[myColumns];
}
}
This should work now.
Try replacing:
*myArr = new int[myRows];
by
myArr = new int*[myRows];
You should use std::vector<>. It deals with all the problems of memory allocation and deallocation.
And it does so without any bugs.
And then you focus yourself on the real goals of your algorithm. Not on memory management :-)
typedef std::vector<int> Ints;
typedef std::vector<Ints> Matrix;
Matrix myArray;
I'm not sure if you're project requires you to use multi-level pointers, if it doesn't another way you can approach this problem is to just treat the multi-dimensional array as one big flat array.
That means when you reach the end of a row, the index after that would be the first element of the next row. Here's how the code might look:
// In this approach the double pointer int**
// is replaced with just a simple int*
int *myArr;
// Here's your Matrix ctor. Note the use of the initializer list
Matrix::Matrix(int n, int m) : myRows(n), myColumns(m)
{
initialize();
}
void Matrix::initialize()
{
myArr = new int[myRows * myColumns];
/* This loop is no longer needed since we're allocating
one big chunk at once.
for (int i=0; i < 3; i++)//Only set to 3 since myRows is acting crazy
{
myArr[i] = new int[myColumns];
}
*/
}
// To retrieve stuff from your array
// you would do something like this:
int Matrix::operator() (const int x, const int y)
{
return myArr[x * myRows + y];
}