C++ Initiating object with array in constructor - c++

I am trying to initiate an object with an array. Is there a way to do it with pointers or should i find another way to do this.
EDIT: I want to write this code with dynamic memory allocation, I know vector is better way to solve this.
#include <iostream>
template <class t>
class die {
private:
int sideCount;
t* valueOfSides;
public:
die(int side, t arr[]) {
sideCount = side;
valueOfSides = (t*)malloc(side * sizeof(t));
for (int counter; counter < side; counter++) {
valueOfSides[counter] = val[counter];
}
}
~die() {
free(valueOfSides);
}
};
int main() {
die<int> sixsided(6, {1,2,3,4,5,6});
}

The right ways to do this would be
std::vector<t> valueOfSides;
template<size_t len> die(t (&arr)[len])
: valueOfSides(std::begin(arr), std::end(arr))
{}
or
std::vector<t> valueOfSides;
die(std::initializer_list<t> arr) : valueOfSides(arr) {}
I think. Though really, the best answer is
std::vector<t> valueOfSides;
die(std::vector<t> arr) : valueOfSides(std::move(arr)) {}
One should never use raw pointers to own memory in C++, and virtually never use new or malloc. As it is, you have undefined behavior in your code because of misusing malloc.
If you're absolutely insane, or doing homework, it can be done with raw pointers, though I doubt I can get it entirely right without tests and a compiler.
template<class t>
class die {
private:
int sideCount;
t* valueOfSides;
public:
die(int side, t* arr) {
sideCount = 0;
std::size_t buffer_size = sizeof(t)*side;
char* buffer;
try {
buffer = new char[side];
valueOfSides = reinterpret_cast<t*>(buffer);
for(int i=0; i<side; i++) {
new(valueOfSides+i)t(arr[i]);
sideCount++;
}
} catch(...) {
for(int i=sideCount; i>=0; i--)
(valueOfSides+i)->~t();
delete[]buffer;
throw;
}
}
die& operator=(die&& rhs) {
sideCount = rhs.sideCount;
valueOfSides = rhs.valueOfSides;
rhs.valueOfSides = nullptr;
rhs.sideCount = 0;
return *this;
}
//die& operator=(const die& rhs) not shown because its super hard.
~die() {
for(int i=sideCount; i>=0; i--)
(valueOfSides+i)->~t();
delete[]reinterpret_cast<char*>(valueOfSides);
}
};
As we've said before, getting this stuff right is crazy hard. Use a std::vector.

Use std::vector.
#include <iostream>
#include <initalizer_list>
#include <vector>
template<class T>
class die {
public:
die() = default;
die(std::initializer_list<T> list)
: sides{list}
{ /* DO NOTHING */ }
private:
std::vector<T> sides{};
};
int main() {
die<int> sixsided({1,2,3,4,5,6});
}

One way you can do this, using more of a C technique, is a variable argument list:
#include <cstdarg>
#include <iostream>
template <class t>
class die {
private:
int sideCount;
t* valueOfSides;
public:
die(int side, ...) {
sideCount = side;
valueOfSides = new t[side];
va_list args;
va_start(args, side);
for (int counter = 0; counter < side; counter++) {
valueOfSides[counter] = va_arg(args, t);
}
va_end(args);
}
~die() {
delete[] valueOfSides;
}
};
int main() {
die<int> sixsided(6, 1,2,3,4,5,6);
}
Rather than passing an array, you're passing the parameters individually (i.e. no need for a temporary array) and using a va_list to access them.
Also, the calls to malloc and free were replaced with new and delete which is the C++ way of allocating and deallocating memory.

The C++ solution:
template <class t>
class die {
private:
int sideCount;
t* valueOfSides;
public:
die(int side, t arr[]) {
sideCount = side;
valueOfSides = new T[side]
for (int counter = 0; counter < side; counter++) { //always initialize variables
valueOfSides[i] = arr[i];
}
}
~die() {
delete[] valueOfSides;
}
};
int main() {
int arr[6] = { 1,2,3,4,5,6 };
die<int> sixsided(6, arr);
}
The new operator is like malloc and the delete and delete[] operators are like free. They are dynamic allocators.
C solution:
template <class t>
class die {
private:
int sideCount;
t* valueOfSides;
public:
die(int side, t arr[]) {
sideCount = side;
valueOfSides = (t*)malloc(side * sizeof(t));
for (int counter = 0; counter < side; counter++) { //always initialize variables
valueOfSides[i] = arr[i];
}
}
~die() {
free(valueOfSides);
}
};
int main() {
int arr[6] = { 1,2,3,4,5,6 };
die<int> sixsided(6, arr);
}
Note: in C the <iostream> header will not work, this is C++ only.
There are other containers, namely std::vector, that can work, but this is the solution for your answer.

Related

How to create our own dynamic array class in c++

I was trying yo create my own array class (similar to std::vector) just for fun but there is some problem...
The Array class code itself works and compiles successfully but throws an error if i try to instantiate an object of Array class.
#include<iostream>
template<typename type, int size>
class Array
{
private:
type _mArray[size] = new type[size];
public:
int Access(int index)
{
return _mArray[index];
}
int Len()
{
return size;
}
void Insert(int index, type val)
{
_mArray[index] = val;
}
~Array()
{
delete[] _mArray;
}
};//All code above compiles successfully
int main()
{
Array<int, 2> name; //this line throws an error
}
I am a bit new to C++ so if someone can explain then I will be very thankful....
Btw here is the error
Array initializer must be an initializer list
type _mArray[size] = new type[size];
The template instantiates with: type is int, and size is 2. Therefore, this becomes:
int _mArray[2] = new int[2];
This obviously does not make much sense. If you put this, verbatim, in your main() your C++ compiler will also serve you with the same complaint.
It's clear that the intent here is, simply:
type _mArray[size];
And nothing else.
P.S. Now, let's go back and reread what the suffering C++ compiler was struggling to communicate here:
Array initializer must be an initializer list
int _mArray[2] is, obviously, an array. There's an = stuck after it. Ok, this must be array initialization. How do you initialize an array in C++? With a braced initialization list, of course. This would be something like this, for example:
int _mArray[2]={1, 2};
The C++ compiler saw nothing of that kind, and was trying to tell you that.
#include<iostream>
template<typename type, int size>
class Array
{
private:
type * _mArray ;
public:
int Access(int index)
{
return _mArray[index];
}
int Len()
{
return size;
}
Array()
{
_mArray = new type[size];
}
~Array()
{
delete[] _mArray;
}
int& operator[](int index){
return _mArray[index];
}
};//All code above compiles successfully
int main()
{
Array<int, 2> name;
name[0] = 1024;
name[1] = 100;
for(int i= 0; i< name.Len(); i++)
{
std::cout<< name[i] << std::endl;
}
}
You can get it to build using the following minimal change:
## -4,7 +4,7 ## template<typename type, int size>
class Array
{
private:
- type _mArray[size] = new type[size];
+ type* _mArray;
public:
int Access(int index)
{
## -18,6 +18,10 ## class Array
{
_mArray[index] = val;
}
+ Array()
+ {
+ _mArray = new type[size];
+ }
~Array()
{
delete[] _mArray;
Basically, you should be initializing the array in your constructor, and store a pointer to it as a class member. The following code builds:
#include<iostream>
template<typename type, int size>
class Array
{
private:
type* _mArray;
public:
int Access(int index)
{
return _mArray[index];
}
int Len()
{
return size;
}
void Insert(int index, type val)
{
_mArray[index] = val;
}
Array()
{
_mArray = new type[size];
}
~Array()
{
delete[] _mArray;
}
};//All code above compiles successfully
int main()
{
Array<int, 2> name; //this line throws an error
}

How to use assignment operator on proxy of index operator

In the following code I made a template class, Its initialized in main function and I'm trying to assign char* as you can see below but It isn't working. I think the issue is in assign operator function I defined in Proxy class but I can't figure it out
#include <iostream>
using namespace std;
template <class T>
class Vector {
public:
T *p;
Vector(int size) {
p = new T[size];
}
class Proxy {
Vector &a;
int i;
public:
Proxy(Vector &a, int i) : a(a), i(i) {
}
void operator=(const T x) {
a.p[i] = x;
}
};
Proxy operator[](int i) {
return Proxy(*this, i);
}
};
int main() {
Vector<char *> sv1(2);
sv1[0] = "John";
sv1[1] = "Doe";
}
I'm getting following error;
I already tried setting parameter in assignment operator function to const, I also tried implicitly typecasting to T nothing has worked
Try this:
using namespace std;
template <class T>
class Vector {
public:
T* p;
int sz;
Vector(int size) {
p = new T[size];
sz = size;
}
template<class T>
class Proxy {
Vector<T>& v;
int i;
public:
Proxy(Vector<T>& vec, int index) :v(vec),i(index) { }
void operator= (const T val) { v.p[i] = val; }
};
Proxy<T> operator[](int index) { return Proxy<T>(*this, index); }
};
Your code will work with any basic type, (int, char, double) and pointers, but not, for example, with this:
int main() {
Vector<char*> sv1(2);
sv1[0] = "John";
sv1[1] = "Doe";
}
Firstly, the Vector points to a char*, not a string literal (const char*). You'd have to cast it using a C-style cast or a const_cast. Example:
int main() {
Vector<char*> sv1(2);
sv1[0] = const_cast<char*>("John"); //succeeds
sv1[1] = (char*)"Doe"; //succeeds
sv1[0] = "John"; //fails
sv1[1] = "Doe"; //fails
}
A string literal is always a const char* in C++.
You'll have same error writing code:
char * whatever = "something";
This code is absolutely wrong at least for string:
void operator=(const T x)
{
a.p[i] = x;
}
Step 1: allocate buffer;
Step 2: copy string to allocated buffer.
Your code is OK for primitives like char, int, etc. The following code should work:
int main() {
Vector<char> sv1(2);
sv1[0] = 'J';
sv1[1] = 'D';
}

C++ how to declare an self defined array in generic programming

I have a class template
template <class T> class Collection
{
private:
int size;
int type;
T* Arr;
int Case;
public:
void ArrayGenerating() {
switch(type) {
case 1:
Arr = new T[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i] = static_cast <T> (rand()) % size;
}
case 2:
Arr = new T[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i] = static_cast <T> (rand()) / (static_cast <T> (RAND_MAX/size));
}
case 3:
Arr = new T[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i].setNumerator(static_cast <int> (rand()) % size);
srand((unsigned)time(NULL));
Arr[i].setDenominator(static_cast <int> (rand()) % size);
}
}
}
};
I want to creat an random array of generic data type
with type 1, that is an interger array. type 2, an float array. type 3, I have an self-defined data type "fraction". But when I compile the programm, there are errors:
Error 1 error C2228: left of '.setNumerator' must have class/struct/union
Error 2 error C2228: left of '.setDenominator' must have class/struct/union
So if there are any solution for this complication?
I guess, type is a constant depending on T. Otherwise it would make no sense to have a T* point to an int, when T is a float. If that is true, it is not necessary at all.
I think, what you are looking for is template specialization (untested code):
// this is common to all cases.
class CollectionBase {
protected:
int size;
};
// the general template is not defined
// the compiler will complain whenever T is neither int, nor float, nor fraction.
template<class T> class Collection;
// here come the specializations
template<> class Collection<int>: private CollectionBase
{
private:
int* Arr;
public:
void ArrayGenerating() {
Arr = new int[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i] = static_cast<int>(rand()) % size;
}
}
};
template<> class Collection<float>: private CollectionBase
{
private:
float* Arr;
public:
void ArrayGenerating() {
Arr = new float[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i] = static_cast<float>(rand()) / (static_cast<float>(RAND_MAX/size));
}
}
};
template<> class Collection<fraction>: private CollectionBase
{
private:
fraction* Arr;
public:
void ArrayGenerating() {
Arr = new fraction[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i].setNumerator(static_cast <int> (rand()) % size);
srand((unsigned)time(NULL));
Arr[i].setDenominator(static_cast <int> (rand()) % size);
}
}
};
Please note, that this kind of code is dangerous. Consider std::vector<> instead of managing dynamically allocated array yourself.
Also be aware, that as a rule of thumb all methods of your class should be safely callable as soon as the constructor has finished. In your code any function that accesses Arr uses a random pointer to some memory, before ArrayGenerating() has run. Whenever you call ArrayGenerating() twice for some reason, your code will leak memory, because you never bother to delete[] your array before creating a new one.
The best tool C++ gives you for memory management is constructors and destructors. You are best of, when you encapsulate every resource, that you have to release once in a while, in a handler object. In this case std::vector already does what you need.
So here is a full (yet untested) most generic solution for you. I'd start with a free function to create random numbers:
template<typename T> struct dist{
using uniform = std::uniuniform_int_distribution<T>;
};
template<> struct dist<float> {
using uniform = std::uniuniform_real_distribution<float>;
};
template<typename T>
std::vector<T> createRandomNumbers(size_t s) {
auto e1 = std::default_random_engine{std::random_device{}()};
auto u = dist<T>::uniform{0, static_cast<T>(s)};
auto r = std::vector<T>(s, 0);
for( auto& i: r ) i = u(e1);
return r;
}
// fraction need a specialization
template<>
std::vector<fraction> createRandomNumbers<fraction>(size_t s) {
auto e1 = std::default_random_engine{std::random_device{}()};
auto u = dist<int>::uniform{0, static_cast<int>(s)};
auto r = std::vector<fraction>(s, 0);
for( auto& i: r ) {
i.setNumerator(u(e1));
i.setDenominator(u(e1));
}
return r;
}
Now we implement a Collection class template like yours, if we really still need it:
template <typename T> Collection {
private:
// this will handle all your memory management needs
std::vector<T> randoms;
public:
Collection(size_t s) :
randoms{createRandomNumbers<T>(s)}
{};
createNewRandoms(size_t s) {
std::swap(randoms, createRandomNumbers<T>(s));
};
// whatever else is necessary
};
Why would you want to do this and make your life infinitely more difficult?
It could be as simple as this:
#include <iostream>
#include <chrono>
#include <random>
template<class type_t, std::size_t size>
class Array
{
private:
type_t arr[size];
public:
Array()
{
for (std::size_t i = 0; i < size; ++i)
{
//nice C++ random number generation
auto seed = static_cast<unsigned>(std::chrono::system_clock::now().time_since_epoch().count());
std::minstd_rand0 randm(seed);
arr[i] = randm();
}
}
//test function
void print()
{
for (int i = 0; i < size; ++i)
std::cout << arr[i] << " ";
}
};
int main()
{
Array<int, 4> arr;
arr.print();
std::cin.get();
}
Try to get away from C-style C++. Join the dark side.
Note: I won't comment on your use of C functions or other problems. Others have already told you how to avoid them.
A type member in a class template somehow defeats the purpose of generic programming, doesn't it? You should get rid of your type and replace the switch with template specialisation.
Here is a simple example to get you started:
// Collection for all T except of `fraction`
template <class T> class Collection
{
private:
int size;
T* Arr;
int Case;
public:
void ArrayGenerating() {
Arr = new T[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i] = static_cast <T> (rand()) % size;
}
};
};
// Collection for `fraction`
template <> class Collection<fraction>
{
private:
int size;
fraction* Arr;
int Case;
public:
void ArrayGenerating() {
Arr = new fraction[size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i].setNumerator(static_cast <int> (rand()) % size);
srand((unsigned)time(NULL));
Arr[i].setDenominator(static_cast <int> (rand()) % size);
}
}
};
This is the simplest kind of template specialisation but may lead to a lot of code duplication. You can get around this problem, too, though. For example, you could extract all common parts into a common private base class, something like this:
namespace detail
{
template <class T> class CollectionBase
{
protected:
int size;
T* Arr;
int Case;
};
}
template <class T> class Collection : detail::CollectionBase<T>
{
public:
void ArrayGenerating() {
Base::Arr = new T[Base::size];
for (int i = 0; i < Base::size; i++) {
srand((unsigned)time(NULL));
Base::Arr[i] = static_cast <T> (rand()) % Base::size;
}
};
private:
using Base = detail::CollectionBase<T>;
};
template<> class Collection<fraction> : detail::CollectionBase<fraction>
{
public:
void ArrayGenerating() {
Base::Arr = new fraction[Base::size];
for (int i = 0; i < size; i++) {
srand((unsigned)time(NULL));
Arr[i].setNumerator(static_cast <int> (rand()) % size);
srand((unsigned)time(NULL));
Arr[i].setDenominator(static_cast <int> (rand()) % size);
}
}
private:
using Base = detail::CollectionBase<fraction>;
};
Generally, read more about template specialisation and you will certainly find the right solution:
http://en.cppreference.com/w/cpp/language/template_specialization
http://en.cppreference.com/w/cpp/language/partial_specialization

How do I sort strings in a vector?

I have a program that uses something I made called "SortableVector," with a parent called SimpleVector. The Simple Vector is fine, and so is most of SortableVector, but the problem is the sort function in SortableVector. It sorts numbers just fine, but I can't get it to sort strings. Here's what I originally had:
template <class T>
void SortableVector<T>::sort()
{
T temp = 0;
for(int i = 0; i < this->size(); i++)
{
for (int count = i+1; count < this->size(); count++)
{
if(this->operator[](0) == int)
{
if (this->operator[](count) < this->operator[](i))
{
temp = this->operator[](count);
this->operator[](count) = this->operator[](i);
this->operator[](i) = temp;
count = i+1;
}
}
}
}
}
Then I tried to use the sort(begin, end) function, but that didn't work either:
template <class T>
void SortableVector<T>::sort()
{
sort(this->operator[].begin(), this->operator[].end();
}
EDIT: To help people understand the problem, here's the whole file:
#ifndef SORTABLEVECTOR_H
#define SORTABLEVECTOR_H
using namespace std;
#include "SimpleVector.h"
#include <algorithm>
#include <fstream>
#include <string>
template <class T>
class SortableVector : public SimpleVector<T>
{
public:
SortableVector(int s) : SimpleVector<T>(s)
{}
SortableVector(SortableVector &);
SortableVector(SimpleVector<T> &obj):
SimpleVector<T>(obj)
{}
void sort();
};
template <class T>
SortableVector<T>::SortableVector(SortableVector &obj):SimpleVector<T>(obj)
{
}
template <class T>
void SortableVector<T>::sort()
{
std::sort(this->operator[].begin(), this->operator[].end());
T temp = 0;
for(int i = 0; i < this->size(); i++)
{
for (int count = i+1; count < this->size(); count++)
{
if(this->operator[](0) == int)
{
if (this->operator[](count) < this->operator[](i))
{
temp = this->operator[](count);
this->operator[](count) = this->operator[](i);
this->operator[](i) = temp;
count = i+1;
}
}
}
}
}
#endif
And this is SimpleVector:
// SimpleVector.h
#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
#include <iostream>
#include <cstdlib>
using namespace std;
template <class T>
class SimpleVector
{
private:
T *aptr;
int arraySize;
void subError(); // Handles subscripts out of range
public:
SimpleVector() // Default constructor
{ aptr = 0; arraySize = 0;}
SimpleVector(int); // Constructor
SimpleVector(const SimpleVector &); // Copy constructor
~SimpleVector(); // Destructor
int size() { return arraySize; }
T &operator[](int); // Overloaded [] operator
void print() const; // outputs the array elements
void push_back(T); // newly added function (implemention needed)
T pop_back(); // newly added function (implemention needed)
};
//****************************************************************
// Constructor for SimpleVector class *
// Sets the size of the array and allocates memory for it. *
//****************************************************************
template <class T>
SimpleVector<T>::SimpleVector(int s)
{
arraySize = s;
aptr = new T [s];
}
//*********************************************
// Copy Constructor for SimpleVector class *
//*********************************************
template <class T>
SimpleVector<T>::SimpleVector(const SimpleVector &obj)
{
arraySize = obj.arraySize;
aptr = new T [arraySize];
for(int count = 0; count < arraySize; count++)
*(aptr + count) = *(obj.aptr + count);
}
// *************************************
// Destructor for SimpleVector class *
// *************************************
template <class T>
SimpleVector<T>::~SimpleVector()
{
if (arraySize > 0)
delete [] aptr;
}
//************************************************************
// SubError function *
// Displays an error message and terminates the program when *
// a subscript is out of range. *
//************************************************************
template <class T>
void SimpleVector<T>::subError()
{
cout << "ERROR: Subscript out of range.\n";
exit(0);
}
//***********************************************************
// Overloaded [] operator *
// This function returns a reference to the element *
// in the array indexed by the subscript. *
//***********************************************************
template <class T>
T &SimpleVector<T>::operator[](int sub)
{
if (sub < 0 || sub >= arraySize)
subError();
return aptr[sub];
}
//********************************************************
// prints all the entries is the array. *
//********************************************************
template <class T>
void SimpleVector<T>::print( ) const
{
for (int k = 0; k < arraySize; k++ )
cout << aptr[k] << " ";
cout << endl;
}
//***************************************************************
// (1) push_back(T val) *
// The push_back function pushes its argument onto the back *
// Of the vector. *
//***************************************************************
template <class T>
void SimpleVector<T>::push_back(T val)
{
aptr[arraySize] = val;
arraySize++;
}
// *****************************************************
// (2) pop_back() *
// The pop_back function removes the last element *
// Of the vector. It also returns that value. *
// *****************************************************
template <class T>
T SimpleVector<T>::pop_back()
{
arraySize--;
T temp = aptr[arraySize];
return temp;
}
#endif
The SimpleVector was provided by the instructor.
You can do without the repeated this-> 99% of the time
You can just invoke operators, instead of invoking them as functions
You can just use std::sort from <algorithm>
Imagining some of the code you didn't show:
#include <vector>
#include <algorithm>
template <typename T>
struct SimpleVector {
std::vector<T> data;
virtual ~SimpleVector() {}
};
template <typename T>
struct SortableVector : public SimpleVector<T> {
void sort() {
std::sort(this->data.begin(), this->data.end());
}
};
#include <iostream>
int main()
{
SortableVector<std::string> sv;
sv.data = {"one","two","three","four"};
sv.sort();
for(auto& s : sv.data)
std::cout << s << ' ';
}
DISCLAIMER This seems a very non-c++ way to design classes. Algorithms and containers are traditionally separated, for good reason. The exception being that member functions sometimes perform operations in more optimal ways (e.g. std::set<>::find instead of std::find)
It should be std::sort(aptr, aptr + arraySize);. Also you should check arraySize > 0 before doing this, if you're intending to catch errors like that instead of having undefined behaviour.
begin and end aren't magic; they rely on the object either being an array (not a pointer), or the object implementing functions .begin() and .end() that return iterators.
You could even define those functions yourself, e.g. SimpleVector<T>::begin() { return aptr; } etc. , but maybe this is not a good idea as it bypasses your bounds-checking. You'd have to actually write an iterator class instead of returning a pointer, which is more trouble than you're ready for :)
NB. Everywhere you write this->operator[](foo), it would be clearer to write (*this)[foo]

C++ struct constructor error

i`m working on my assignment for univ, and since some parts are not really good explained i got some problems there is my structure and my constructor for it, it has to be dynamical but i get the fallowing error. Some help is really appreciated thank you.
.h:
const int days=31;
const int exp=6;
struct Array{
int days;
int exp;
int **M;
};
.cpp:
void constr(Array &loc){
//Construct of 31*6 Matrix, were 31 nr. of days and 6 specific types:
//0-HouseKeeping, 1-Food, 2-Transport, 3-Clothing, 4-TelNet, 5-others
loc.days = days;
loc.exp = exp;
loc.M=malloc(loc.days*sizeof(int*));
for(int i=0; i<loc.days;i++ ){
loc.M[i] = malloc(loc.exp*sizeof(int));
for (int j = 0; j< loc.exp; j++){
loc.M[i][j] = 0;
}
}
}
error:
..\src\structs.cpp: In function 'void constr(Array&)':
..\src\structs.cpp:7:36: error: invalid conversion from 'void*' to 'int**' [-fpermissive]
..\src\structs.cpp:9:40: error: invalid conversion from 'void*' to 'int*' [-fpermissive]
Since you asked for C++ constructors in your comment... See the code below. I also replaced your two-dimensional C-style array with a C++ vector. I added code comments to the relevant lines:
Array.h:
#pragma once
#include <vector>
struct Array
{
// this is a c++ constructor declaration
Array(int daysParam, int expParam);
int days;
int exp;
// use a vector of vectors instead allocating with new or malloc
// it is easier to initialize and the compiler will clean it up for you
std::vector<std::vector<int> > M;
};
Array.cpp:
#include "Array.h"
// Array constructor definition with initializer list
// all data members are initialized here by invoking their constructor
Array::Array(int daysParam, int expParam)
: days(daysParam),
exp(expParam),
M(daysParam, std::vector<int>(expParam, 0))
{
}
Example for usage of Array (Program.cpp):
#include "Array.h"
int main()
{
// create a new Array, using the c++ constructor
Array myArray(31, 6);
// access elements in the 2-dimensional array
int singleValue = myArray.M[15][3];
return 0;
}
I strongly advise you to read a book about C++
Since this is C++:
loc.M = new int*[loc.days];
for(int i=0; i<loc.days;i++ ){
loc.M[i] = new int[loc.exp];
for (int j = 0; j< loc.exp; j++){
loc.M[i][j] = 0;
}
}
loc.M = (int**)malloc(loc.days*sizeof(int*));
loc.M[i] = (int*)malloc(loc.exp*sizeof(int));
Please, stop using std::vector > or, worse T tab[][] for representing a 2D array. You should use a 1D array to store data, a an index array to store row pointers. That way, your data remains contiguous, and you still can have a nice syntax.
template<typename T>
class Array2D
{
std::vector<T> m_data;
std::vector<T*> m_ptr;
size_t m_iWidth;
size_t m_iHeight;
void Link(void)
{
for (unsigned int j = 0; j < m_iHeight; ++j)
m_ptr[j] = &m_data[j * m_iWidth];
}
public:
Array2D(void)
{
};
Array2D(const size_t i_width, const size_t i_height) :
m_iWidth(i_width),
m_iHeight(i_height),
m_data(i_width * i_height),
m_ptr(i_height)
{
Link();
}
void Resize(const size_t niou_width, const size_t niou_height)
{
if (m_iWidth == niou_width && m_iHeight == niou_height)
return;
m_iWidth = niou_width;
m_iHeight = niou_height;
m_data.resize(niou_height * niou_width);
m_ptr.resize(niou_height);
Link();
}
typename std::vector<T>::iterator begin(void)
{
return m_data.begin();
}
typename std::vector<T>::iterator end(void)
{
return m_data.end();
}
void assign(T value)
{
m_data.assign(m_iWidth * m_iHeight, value);
}
Array2D(const Array2D& a) :
m_iWidth(a.m_iWidth),
m_iHeight(a.m_iHeight),
m_data(a.m_data)
{
m_ptr.resize(m_iHeight);
Link();
}
Array2D& operator=(const Array2D a)
{
swap(*this, a);
return *this;
}
template <typename U>
friend void swap(Array2D<U>& first, Array2D<U>& second)
{
using std::swap;
swap(first.m_iHeight, second.m_iHeight);
swap(first.m_iWidth, second.m_iWidth);
swap(first.m_data, second.m_data);
swap(first.m_ptr, second.m_ptr);
}
~Array2D()
{
};
T* operator[](const size_t ligne)
{
return m_ptr[ligne];
};
const T* operator[](const size_t ligne) const
{
return m_ptr[ligne];
};
T& operator()(const size_t col, const size_t lig)
{
return m_ptr[lig][col];
};
const T& operator()(const size_t col, const size_t lig) const
{
return m_ptr[lig][col];
};