Does it need to initialise the variable after allocating memory? - c++

I am trying to implement matrix multiplication in c++. I found a sample code using a class that writes in .h and .cpp files. This is just a part of the code that related to my question:
#include "Matrix.h"
// Constructor - using an initialisation list here
Matrix::Matrix(int rows, int cols, bool preallocate): rows(rows), cols(cols), size_of_values(rows * cols), preallocated(preallocate)
{
// If we want to handle memory ourselves
if (this->preallocated)
{
// Must remember to delete this in the destructor
this->values = new double[size_of_values];
}
}
void Matrix::matMatMult(Matrix& mat_left, Matrix& output)
{
// The output hasn't been preallocated, so we are going to do that
output.values = new double[this->rows * mat_left.cols];
// Set values to zero before hand
for (int i = 0; i < output.size_of_values; i++)
{
output.values[i] = 0;
}
I wonder why they initialised using the output matrix with 0s output.values[i] = 0; while it has been allocated memory before?

From cppreference on new expression:
The object created by a new-expression is initialized according to the following rules:
[...]
If type is an array type, an array of objects is initialized.
If initializer is absent, each element is default-initialized
If initializer is an empty pair of parentheses, each element is value-initialized.
"default-initialized" ints are colloquially not initialized. They have indeterminate values. The empty pair of parantheses refers to what Ted mentioned in a comment:
output.values = new double[this->rows * mat_left.cols]{};
Value initialization is described here. The case that applies here is
otherwise, the object is zero-initialized.
I wonder why they initialised using the output matrix with 0s output.values[i] = 0; while it has been allocated memory before?
Allocating memory and initializing an object are two seperate steps. Yes, the elements have to be initialzed, allocating memory is not sufficient.

Related

C++ Dynamic Array allocation in Classes

I am currently learning basics of c++, and am coming across an issue with the class array below.
class Arrayclass {
private:
int arraySize;
float array[];
public:
Arrayclass(int arraySize) {
float * array = new float[arraySize]();
}
~Arrayclass() {
delete[] array;
}
}
As far as I am aware, I am having issues with the array being initialized in the constructor not actually corresponding to a stored array in the new class, thus when I am initializing a new class in my main, the array created holds 0 values. I apologize my explanation is unclear, just trying to understand how the array initialized in the constructor correlates to the array in my private.
float array[]
either is an extension or just doesn't compile. For a C-style static array, Type name[constexpr_size] is used. For a dynamic array, Type* name is stored as a pointer to the beginning of the storage allocated.
Dynamic Array
OK, we need the second option. Then, we start with your snippet
class Array { // "class Arrayclass" -> "class Array", no need to repeat ourselves
private:
float* array{};
int size{}; // "Array::arraySize" -> "Array::size", again
public:
~Array() { delete[] array; } // your destructor is fine
};
(see member initializer as an explanation to those {} initializers in float* array{} and int size{}).
What about
Arrayclass(int arraySize) { float * array = new float[arraySize](); }
, you create a local float* which dies at the end of scope (=the constructor). You probably meant to store that newly allocated array in (this->)array:
Array(int newSize) { // BAD CODE, see below
array = new float[newSize]{};
size = newSize;
}
but the code above is like writing float* p; p = something (create default, than initialize it) instead of float* p{something} (initialize on creation), let's improve it by using member initializer list:
Array(int newSize): array{new float[newSize]{}}, size{newSize} {}
Now, your array (almost) can construct and destruct properly.
==========
However, there's still an issue left: code such as
{
Array a1{42};
Array a2{a1}; // copy construction
}
has undefined behavior and in practice (in this case) should/might crash your application. Why? Because it works as something like (sizes omitted):
{
float* array1{new float[42]{}};
float* array2{array1};
delete[] array1;
delete[] array2; // that UB (double free); the same dynamic array is deleted twice
}
Well, it is a topic for another "lesson". See the rule of three (five) (zero). In general, see RAII and copy/move-semantics.

Initialize vector passed by reference

I have a class Pixel and a class Image with a function used to update a pixel line. I want to initialize the pixel line. My problem is to initialize the vector. Actually I have this :
bool UpdateLine(std::vector<Pixel>& line, int nb)
{
bool noError = true;
line = new std::vector<Pixel>(nb);
// Do some stuff
return noError;
}
When I try this I have :
no viable overloaded '='
How can I initialize the vector ?
The expression you are using:
new std::vector<Pixel>(nb)
returns a pointer to std::vector<Pixel> (i.e.: std::vector<Pixel> *), and not a std::vector<Pixel>, which is what you need.
A distinction between initialization and assignment has to be done: you are assigning to line and not initializing it.
You can create a new vector and assign it to line by means of an assignment operator:
line = std::vector<Pixel>(nb);
What you do is assignment, not initialization.
Initializing a vector could be done like this:
std::vector<int> second (4,100); // four ints with value 100
In your case however, the vector is already declared outside of the function, so in that case you use vector::resize and do this:
line.resize(nb); // creates 'nb' objects 'Pixel'
PS: You don't need new keyword, except if you dynamically allocating memory for your vector.

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.

Initializing an internally allocated matrix

I have to write a constructor for implementing a function for initializing an internally allocated matrix. The given code looks like (only constructor):
Matrix(const float* m, size_t n) : _n(n), _m(0lu)
{
//Missing
}
So, my first question is: What does the part behind the ':' mean (_n(n), _m(0lu))?
Furthermore, as far as I know, I need a return pointer to the memory I am allocating. Is this correct? My first idea was to use posix_memalign(...). Would this be correct?
Thank you very much!
I am assuming this basic object:
class Matrix
{
// stuff
private:
size_t _n;
float* _m;
}
The part of the constructor is an initialization list. It is synonymous to wiring:
Matrix(const float* m, size_t n)
{
_n = n;
_m = 0lu;
}
Here is a good decription, why you want to use them: [10.6] Should my constructors use "initialization lists" or "assignment"?
But that does not solve your initial problem: "function for initializing an internally allocated matrix"
What the constructor does is copy the size (n) and initialize the pointer to NULL. (NULL is synonymous with 0 [1]) So you need some way to internally allocate and initialize.
I have one problem with the Matrix class. Normally a matrix has 2 dimension, so either it is a NxN matrix or n is the element count and we have no idea what dimension the matrix is. I will assume that it is NxN matrix, since this is quite often used in computer graphics.
Step 1: internally allocated
So, allocate some memory:
_m = new float[n*n];
This can replace the assignment to NULL, since why should it be first set to NULL and then change right after.
Step2: initialized
Assuming that the calling code put sufficient data into m, just use memcpy:
std::memcpy(_m, m, n*n*sizeof(float));
If you feel masochistic, you can also copy the elements each:
for (unsigned int i = 0; i < n*n; i++)
{
_m[i] = m[i];
}
So your final constructor looks like so:
#include <cstring>
Matrix(const float* m, size_t n)
: _n(n), _m(new float[n*n])
{
std::memcpy(_m, m, n*n*sizeof(float));
}
Finally, since you allocated memory you should not forget to delete it in the destructor:
Matrix::~Matrix()
{
delete [] _m;
}
Note the array deleting operator.
[1] In C++11 and C99 this is not fully true under certain circumstances, but these are details and irrelevant.
:_n(n), _m(0lu)
is member internalizer list. Means _n(which seems to be member variable) is assing n to it and simialr for _m
More details here

Why do I Get Different Results Using Array?

I've made a simple program that counts matrices, here's the code:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int result[3] = {0,0,0};
int matrixc[3][6] = {
{0,0,0,0,0,1},
{0,0,0,1,1,1},
{1,0,1,0,0,1}
};
for(int x=0;x <3;x++)
{
for(int y=0;y < 6;y++)
{
result[x] += (matrixc[x][y] * pow(2,6-y));
}
cout << result[x] << endl;
}
}
The output is what I wanted, it is: 2,14,and 82.
But, when I delete the initialization in the integer array of result:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int result[3]; //deleted initialization
int matrixc[3][6] = {
{0,0,0,0,0,1},
{0,0,0,1,1,1},
{1,0,1,0,0,1}
};
for(int x=0;x <3;x++)
{
for(int y=0;y < 6;y++)
{
result[x] += (matrixc[x][y] * pow(2,6-y));
}
cout << result[x] << endl;
}
}
I got odd outputs: 1335484418,32618, and 65617.
Would you like to explain me why would the output be different between an array with and without an initialization?
Actually, I don't want to initialize all result array, because I have a huge data of matrices.
Is it possible if I use std::vector without initializing all of the result array?
Would you like to explain me why would the output be different between an array with and without an initialization?
Without initialisation, automatic variables aren't initialised. They will have an indeterminate value, depending on what happened to be in the memory they occupy.
Actually, I don't want to initialize all "result" array, because I have a huge data of matrices.
You can zero-initialise the whole array, even if it's huge, like this:
int result[huge] = {};
although, if it is huge, then it shouldn't be an automatic variable. These are typically kept on the stack, which is typically not huge and liable to overflow if you put too much stuff on it.
Is it possible if I use std::vector without initializing all of the "result" array?
Yes, a vector will zero-initialise its elements by default.
Without the initialization, the result array contains undetermined values, i.e. values that could be anything that fits into an int.
As I mentioned in my comment if you do not initialize result it will have undetermined values. Later on your are then adding a value to an unknown value which will still be an unknown value. In this situation you need to initialize your data, can zero initialize like so:
int result[3] = {} ;
Would you like to explain me why would the output be different between an array with and without an initialization?
Seriously? If you don't initialize the array elements they are not initialized!
That means they contains junk data, so when you do result[x] += xxx; you are adding to junk, so you get more junk.
Actually, I don't want to initialize all "result" array, because I have a huge data of matrices.
Then you shouldn't rely on their initial value being zero.
You can do this:
int result[3] = { }; // initialize all elements to zero
Is it possible if I use std::vector without initializing all of the "result" array?
std::vector always initializes its members.
When you delete the initialization of the result array, those locations are initially set to unspecified, arbitrary values. You then add to this arbitrary value within the for loop, and end up those unexpected results. The results may be completely different the next time you run your program.
Also, since result[x] += ... reads from an uninitialized variable, deleting the initialization results in your code having undefined behavior.
If you switch over to using a vector you can zero initialize it as
std::vector<int> result(count); // zero initialized with `count` elements
or
std::vector<int> result; // contains zero elements
result.resize(count); // now it contains `count` elements, all set to 0