How to properly assigning a dynamically create an int and assign it to a dynamic array array with values? - c++

I am working on an assignment for my c++ class where I need to dynamically assign a new int, array, and pointer from another pointer to practice dynamic memory allocation.
At first, I was struggling with creating a new int to provide an int for my new array, but I got it to compile and was wondering if my declarations were correct.
int *dmaArray = new int;
*dmaArray = 4;
I then took that and put it into a dynamically created array, but I don't know how to declare values of the array as it errors out saying "cannot convert to int". I did some thinking and I believe it's because it was declared and needs to be initialized at the declaration; I can't because the declaration is already a declaration (new) in itself.
int * nodeValues = new int[*dmaArray];
nodeValues[*dmaArray] = {6, 2, 28, 1};
A loop wouldn't work to assign values after since the values aren't consecutive or in any pattern. (well, regardless, I would need to use an array because the assignment said so.

This is not how to to declare a dynamic array and initialize it:
int * nodeValues = new int[*dmaArray];
nodeValues[*dmaArray] = {6, 2, 28, 1};
So you declare it this way:
int* nodeValues = new int[dmaArray];
And to assign values to it use loops or manually:
nodeValues[0] = 6;
nodeValues[1] = 2;
nodeValues[2] = 28,
nodeValues[3] = 1;
Remember arrays use indexes to read/write its elements as the fact being some sort of data of the same type contiguous to each other in memory.
So if you want to print the array:
for(auto i(0); i != dmaArray; ++i)
std::cout << nodeValues[i] << ", ";
Finally you should clean memory dynamically allocated after finishing with it because the compiler doesn't do it for you:
delete[] nodeValues;

I figured out how:
int * nodeValues = new int[*dmaArray]{6,5,28,1};

Related

C++ linked list declaration

I come across a code as follow:
int* list = new int[5];
I never saw such declaration. What does it do? I suppose list is a pointer to an int? Using VS debug environment, I can see list having one int value. So how are the other element accessed? Thanks.
The statement is called badly-mannered dynamic (memory) allocation, involving two operators, new (new[]) and delete (delete[]). The new operator allocates memory and the delete operator deallocates memory.
Since it's a chunk of memory assigned to a pointer, it behaves mostly the same as an array (int list[5]), so you should access it as usually as you do with a pointer. Like
int *list = new int[5];
list[0] = 10; list[3] = 25; // Whatever
for (int i = 0; i < 5; i++)
list[i] = 1+1;
You can see a list of topics about dynamic allocation in C++ on Stack Overflow here.
This is not a linked list, but a construct known as dynamic memory. If you want to create an array normally, you would write something like
int myArray[3] = {
1, 2, 3
};
Notice that when I write the size of myArray (3), I use a constant expression; If I were to write
int x = 3;
int myArray[x] = {
1, 2, 3
};
It wouldn’t work, because x is a variable, not a constant expression. Note that even if x is a const, this still wouldn’t work. This is because before the program is run, memory needs to be allocated for the arrays.
When you say int * myData = new int[3], you can create memory on the fly, without constant expressions. In this case, it would be perfectly fine to do this
int x = 3;
int * myData = new int[x];
However, myData is a pointer, not an array, so the common sizeof(x) / sizeof(*x) trick doesn’t work here.
Make sure that after your dynamic memory is no longer of use, you write delete[] myData. This de-allocates the memory block and allows other memory to be stored in its place.
This memory is a block of memory just like an array. A linked list, however, is totally different, and would take a while to explain. Check out the Wikipedia on it.

How to dynamically create a c++ array with known 2nd dimension?

I have a function:
void foo(double[][4]);
which takes a 2d array with 2nd dimension equal to 4. How do I allocate a 2d array so that I can pass it to the function? If I do this:
double * arr[4];
arr = new double[n][4];
where n is not known to the compiler. I cannot get it to compile. If I use a generic 2d dynamic array, the function foo will not take it.
As asked, it is probably best to use a typedef
typedef double four[4];
four *arr; // equivalently double (*arr)[4];
arr = new four[n];
Without the typedef you get to be more cryptic
double (*arr)[4];
arr = new double [n][4];
You should really consider using standard containers (std::vector, etc) or containers of containers though.
typedef double v4[4];
v4* arr = new v4[n];
Consider switching to arrays and vectors though.
I know it may not be what OP has intended to do, but it may help others that need a similar answer.
You are trying to make a dynamic array of statically success array. The STL got your solution: std::vector and std::array
With these containers, things are easy easier:
std::vector<std::array<int, 4>> foo;
// Allocate memory
foo.reserve(8);
// Or instead of 8, you can use some runtime value
foo.reserve(someSize);
// Or did not allocated 8 + someSize, but ensured
// that vector has allocated at least someSize
// Add entries
foo.push_back({1, 2, 3, 4});
// Looping
for (auto&& arr : foo) {
arr[3] = 3;
}
// Access elements
foo[5][2] = 2;
Alternatively to creating a new type and occupying a symbol, you can create a pointer to pointer, and do it like that:
double **arr = new double*[j];
for (int i = 0; i < j; ++i)
{
arr[i] = new double[4];
}
whereas j is the int variable that holds the dynamic value.
I've written a simple code that shows it working, check it out here.

Dynamic memory allocation...how about this type of inititlization?

To create an integer on heap and initialize it to a value 5, we do:
int* a = new int(5);
To create an array of 5 integers on the heap, we do:
int* a = new int[5];
But, if we want to create an array of 5 integers and initialize each of them to 10 in one single instruction, is it possible?
To make things more interesting, let us say that the array size will only be known at run time. How about then?
Also, I know this is a very trivial question, but I'm making this transition from Java and get confused at times with C++, so... if not initialized during declaration, then unlike in Java, C++ primitive data types are not initialized with default values, and contain garbage values, right?
But someone told me that if they are declared as global variables, then they are initialized to default values like in Java...is that true as well? Why?
I prefer:
std::vector<int> a = {10,10,10,10,10};
C++ is a very complex language, with many different (even contradicting) goals.
One of the ideas behind it was that you should not pay in efficiency what you don't need and this is what is behind the concept of uninitialized values.
When you write
int x;
the variable x is initialized if it's at global/namespace scope and instead is not initialized when the definition is in a local scope.
This happens not because who designed C is crazy (of course an initialized value is better) but because initialization at global/namespace scope is free from an efficiency point of view as it's done compile/link/loading time, not at runtime.
Initializing a variable in local scope instead has a cost (small, but non-zero) and C++ inherited from C the idea that shouldn't pay for it if you don't need it, thus if you want your variable initialized to any value simply says so with:
int x = 42;
Note however that an uninitialized variable is not simply "containing a garbage value", it's uninitialized and you are not allowed to read its content as such an operation is "undefined behavior".
There are platforms in which just reading the content of an uninitialized variable may crash ("trap representations": for example hardware with dedicated registers for pointers in which just placing an invalid address in a register - not doing anything with it - provokes an hardware exception).
No, it is not possible to allocate an array with new[] and specify an initial value for the array elements. You have to fill in the array after the allocation is finished, eg:
int count = 5;
int* a = new int[count];
for (int i = 0; i < count; ++i)
a[i] = 10;
...
delete[] a;
That is not very C++-ish. You could use std::fill() to get rid of the loop, at least:
int count = 5;
int* a = new int[count];
std::fill(a, a+count, 10);
...
delete[] a;
A better option is to switch to a std::vector instead, which has a constructor that does exactly what you are looking for:
std::vector<int> a(5, 10); // create 5 elements initialized to value 10
std::vector has a constructor where you can specify the initial size and initial value:
std::vector<int> an_array(size, init_value);
If you want to use a dynamic array using new[], you have to assign the initial value to each element:
int* array = new a[size];
for(int i = 0; i < size; ++i)
array[i] = init_value;
...
delete[] array;
Use std::array if the size is known at compile-time:
std::array<int, 5> myArray = { 1, 2, 3, 4, 5 };
Which is RAII-conform and safe.
You just have to include <array> and <initializer_list>.
In other cases, use std::vector.
This works for me with g++ 4.8.2.
#include <iostream>
int main()
{
int* a = new int[5]{10, 10, 10, 10, 10};
for ( int i = 0; i < 5; ++i )
{
std::cout << a[i] << " ";
}
std::cout << std::endl;
}
Output:
10 10 10 10 10
Update, in response to OP's comment
When you use
std::vector<int> v(5, 10);
the constructor of std::vector used is:
vector( size_type count,
const T& value,
const Allocator& alloc = Allocator());
Let's say you have a class
class MyClass
{
public:
MyClass(int ) {}
};
You can construct a std::vector<MyClass> using:
std::vector<MyClass> v(10, MyClass(50));
or
std::vector<MyClass> v(10, 50);
In the second case, the compiler knows how to implicitly construct a temporary MyClass object given the argument 50 alone. But either way, a temporary MyClass object is being passed to the vector, and that is OK because the argument type of that parameter is const MyClass&, which can bind to a temporary object.

About new[][] and initializing classes in array

#include <iostream>
using namespace std;
class CType{
private:
int val;
public:
CType(): val(0){}
CType(int x): val(x){}
void setVal(int x){ val = x; }
~CType(){ cout << val << " is destructed." << endl;}
};
int main(){
// CType *t = new CType[10](10); // -1-
CType (*t)[10] = new CType[10][10]; // -2-
for(int i = 0; i < 10; ++i){
for(int j = 0; j < 10; ++j){
t[i][j].setVal(10 * i + j);
}
}
delete[] t;
return 0;
}
The above code is a sample I wrote to test new[][] and whether it is possible to initialize instances in dynamic array. My question is:
I intended to create an array of 10 CType instances with val initialized to 10. But this line cannot pass compilation. I have to add a default constructor with no parameter and CType *t = new CType[10]. Is there any way to create an array of instances and invoke constructors with some parameters?
I got puzzled by new int[10][10] which intuitively creates an 10x10 2D array. But I cannot find any official material defining the behavior of new int[][] or new int[][][] etc. Why does new int[10][10] have return type int (*)[10] rather than int** or int[10][10]?
BTW, if I write CType (*t)[10] = new CType[10][10](10), I'll got a compilation error reading A.cpp:13:39: sorry, unimplemented: cannot initialize multi-dimensional array with initializer. Funny, g++ says SORRY.
Update
I'm using g++. But I also tested the code on VS2010. It passed compilation and output the same result as it did in g++.
The variable t in CType (*t)[10] is a pointer which points to an array of 10 CType instances, not an array of 10 CType pointers. So t + 1 points to the place sizeof(CType) * 10 bytes away after t.
The output of my code reveals that the destruct order of delete[] t is 99 to 0. The last element of t + 9 is destructed first.
Is there any way to create an array of instances and invoke constructors with some parameters?
There is since C++11:
CType* t = new CType[10] {10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
// ...
delete[] t;
But in general, you are far better of with vectors in C++:
std::vector<CType> t(10);
// ...
// no need to delete anything manually!
I cannot find any official material defining the behavior of new int[][] or new int[][][] etc.
5.3.4 [expr.new] §5 says:
When the allocated object is an array [...], the new-expression yields a pointer to the initial element (if any) of the array.
Note: both new int and new int[10] have type int* and the type of new int[i][10] is int (*)[10]
Why does new int[10][10] have return type int (*)[10] rather than int**
It couldn't be int**, because then a simple delete[] wouldn't be enough.
or int[10][10]?
Because int[10][10] is not a pointer, but new always returns a pointer.
There is no way to provide a parenthesed initializer in a new-expression of an array type. Don't use legacy C arrays if you can help it. Standard containers provide a superior alternative.
This is specified by the standard. A new-expression that allocates an array returns a pointer to the first element of the array (5.3.4/1). new int[N][4][5][6] creates an array of N elements, each one of type int[4][5][6]. The pointer to the first element of the array will be returned. It will be of type int(*)[4][5][6], not int**** or somesuch. It is easy to understand if you accept that there are no multidimensional arrays in C++, only arrays of arrays. An element of int x[2][3] has type int[3], not int. Words like pointer to the first element do not automatically generalize to pointer to the first element of the first element etc.

Constant for a multi-dimensional array

I'm trying to create a multi-dimensional array, the size of which the user will supply.
So far I have this:
int definedgroups; // for number of groups needed
cout << "Enter the Number of Groups you require: " << endl;
cin >> definedgroups;
const int definedgroups = definedgroups;
int User_Groups [definedgroups] [4];
I believe the array needs constant values, so i tried assigning my variable as a constant but still no luck.
In C++, static arrays, that is, those defined like this:
foo arrayStatic[bar];
require bar to be a constant integer. In other words, the programmer needs to know its value beforehand.
Whenever bar is unknown, a dynamic array could be used instead. They're defined like this:
foo* arrayDynamic;
arrayDynamic = new foo[bar];
Here, bar could be an integer variable.
Don't forget that dynamic memory must be deallocated eventually. So, in this case, we can deallocate arrayDynamic like this:
delete [] arrayDynamic;
A two-dimensional dynamic array is defined analogously:
foo** arrayDynamic2D;
arrayDynamic2D = new foo*[bar];
for (int i = 0; i < bar; i++)
arrayDynamic2D[i] = new foo[baz];
and deallocated in a similar fashion:
for (int i = 0; i < bar; i++)
delete [] arrayDynamic2D[i];
delete [] arrayDynamic2D;
Static memory is allocated in the stack whereas dynamic memory is allocated in the heap.
It's not possible to do it in C++ using static arrays. Use std::vector in a hierarchical way (i.e. vectors of vectors) to implement a multi-dimensional array easily (though not necessarily very efficiently).
E.g.
std::vector<std::vector<double> > array(nrows, std::vector<double>(ncols));
creates a nrows x ncols matrix.
You need dynamic memory allocation using new:
int **User_Groups = new int*[definedgroups];
//Allocate memory for 2nd dimension
for (int i = 0; i < 4; ++i)
User_Groups[i] = new int[4];