So my goal is to have a function that allows to add two dynamically allocated Arrays together. Would the Code I provided work? And is it a good way or are there better ways?
Code:
template <class T>
T add_arrays(T BASE,int size_BASE, T ADD, int size_ADD, bool delInput) {
T new_Alloc = new T[size_BASE + size_ADD];
for (int i = 0; i < size_BASE; i++) {
new_Alloc[i] = BASE[i];
}
for (int i = size_BASE; i < size_ADD; i++) {
new_Alloc[i] = ADD[i];
}
if (delInput) {
delete[] BASE;
delete[] ADD;
}
return new_Alloc;
}
EDIT: According to the Answers, the following above shown Code works.
If needed you can feel free to Copy it
Related
Recently, I started to learn C++ after I have learned Java, and I was instructed to make a dynamic array, so I tried to make a temp variable which contains what I need and then reassign it into the variable I actually want to use.
void Pile::grow(Stone s){
Stone temp[getLength() + 1];
for (int i = 0; i < sizeof(temp) / sizeof(temp[0]); ++i) {
if (sizeof(temp) / sizeof(temp[0]) < 28){
temp[i] = stoneArr[i];
}
}
stoneArr = temp;
}
But the compiler is giving me an error that I cannot reassign it, for some reason I just can't understand.
void Pile::grow(Stone s)
You are not using s anywhere. Are you supposed to add it to the new array you are trying to create?
Stone temp[getLength() + 1];
This is not legal in standard C++. The size of a fixed array must be known at compile time.
Some compilers support "variable length arrays" as a non-standard extension, but do not rely on them if you need to write portable code. See Why aren't variable-length arrays part of the C++ standard?
To allocate an array dynamically at runtime, use the new[] operator instead, eg:
Stone *temp = new Stone[getLength() + 1];
...
delete[] temp;
Or, use the standard std::vector container instead, eg:
#include <vector>
std::vector<Stone> temp(getLength() + 1);
...
for (int i = 0; i < sizeof(temp) / sizeof(temp[0]); ++i)
You cannot use this sizeof trick on a dynamic array, let alone a VLA. sizeof is evaluated only at compile time, not at runtime.
Since you are copying values from an existing array, use the length of that array instead:
for (int i = 0; i < getLength(); ++i)
if (sizeof(temp) / sizeof(temp[0]) < 28)
Hard-coding a 28 here makes no sense. In fact, this whole if check needs to be removed completely.
stoneArr = temp;
This assignment will not work when temp is a VLA. And stoneArr can't be a VLA anyway.
stoneArr needs to be either a Stone* pointer to a new[]'d array (that is managed by following the Rule of 3/5/0), or a std::vector<Stone> (preferred).
With all of that said, try this instead:
private:
Stone *stoneArr;
int arrLength;
...
Pile::Pile()
: stoneArr(NULL), arrLength(0) {
}
Pile::Pile(const Pile &src)
: stoneArr(new Stone[src.arrLength]), arrLength(src.arrLength) {
for (int i = 0; i < arrLength; ++i) {
stoneArr[i] = src.stoneArr[i];
}
}
Pile::~Pile() {
delete[] StoneArr;
}
Pile& Pile::operator=(const Pile &rhs) {
if (&rhs != this) {
Pile temp(rhs);
std::swap(stoneArr, temp.stoneArr);
std::swap(arrLength, temp.arrLength);
}
return *this;
}
int Pile::getLength() const {
return arrLength;
}
void Pile::grow(const Stone &s){
Stone *temp = new Stone[arrLength + 1];
for (int i = 0; i < arrLength; ++i) {
temp[i] = stoneArr[i];
}
temp[arrLength] = s;
delete[] stoneArr;
stoneArr = temp;
++arrLength;
}
Or:
#include <vector>
private:
std::vector<Stone> stoneArr;
...
// std::vector follows the rule of 3/5/0, so let the
// compiler handle Pile(), Pile(const Pile &), ~Pile(),
// and operator= for you...
int Pile::getLength() const {
return stoneArr.size();
}
void Pile::grow(const Stone &s){
stoneArr.push_back(s);
}
I'm writing a cpp program and I want to allocate an array of pointers. the array is holding pointers to type Node which is a generic class i've already implemented. I've tried the following:
Node<int,Song>* songArray = new Node<int,Song>[numOfSongs]();
for (int i = 0; i < numOfSongs; ++i) {
Node<int,Song>* songArray[i] = new Node<int,Song>(i, Song(i, this->artistID));
}
but I get an error saying I don't have operator= (which I did implement for Node).
can anyone advice me on what am I doing wrong?
Thank you very much!
Your types are all over the place.
class Song {
Song(int i, int artistId);
Song(Song const& song);
Song &operator=(Sont const& song);
};
Node<int,Song>** songArray = new Node<int,Song>*[numOfSongs]();
for (int i = 0; i < numOfSongs; ++i) {
songArray[i] = new Node<int,Song>(i, Song(i, this->artistID));
}
I've got some project for my University and I need to perform converting some data from file to matrix representation.
The main problem is that after returning form "returnNeighbours(int node)" destructor is called on neighbours object(as I concluded from running gdb).
I know that destructor is always called when local variable, in function, is initialized, but neihbours is a class member. I won't post everything, because it's not necessary I think. I've got some structures listed below.
representation.cpp
NodeContainer::NodeContainer(){ size = 0; array = nullptr; }
NodeContainer::~NodeContainer(){ size = 0; delete[] array; }
void NodeContainer::allocateMemoryAndSetSize(int n){ size = n; array = new int[size]; }
void MatrixRep::convertDataToMatrixRep(int** array)
{
for(int i = 0 ; i != size; i++)
for(int j = 0; j != size; j++)
matrix[i][j] = array[i][j];
}
NodeContainer MatrixRep::returnNeighbours(int node)
{
deleteNeighboursIfAny();
if(!checkIfNotBeyondMatrix(node))
return neighbours;
neighbours.allocateMemoryAndSetSize(countNeighbours(node));
for(int i = 0, j = 0; i < size; i++)
if(matrix[node-1][i] != 0)
{
neighbours.array[j] = matrix[node-1][i];
j++;
}
return neighbours;
}
void MatrixRep::deleteNeighboursIfAny(){ if(neighbours.array) neighbours.~NodeContainer(); }
bool MatrixRep::checkIfNotBeyondMatrix(int node)
{
if(node == 0 || node > size)
{
std::cerr<<"There is no such a node!\n";
return false;
}
else
return true;
}
int MatrixRep::countNeighbours(int node)
{
int count_non_zero = 0;
for(int i = 0; i != size; i++)
if(matrix[node-1][i] != 0)
count_non_zero++;
return count_non_zero;
}
representation.h
struct NodeContainer
{
int size;
int* array;
NodeContainer();
~NodeContainer();
void allocateMemoryAndSetSize(int);
};
class MatrixRep
{
int size;
NodeContainer neighbours;
int** matrix;
public:
MatrixRep(int);
~MatrixRep();
void convertDataToMatrixRep(int**);
NodeContainer returnNeighbours(int);
void deleteNeighboursIfAny();
bool checkIfNotBeyondMatrix(int);
int countNeighbours(int);
void setupMatrix();
void deleteMatrix();
};
If you would like to return a copy of NodeContainer, you must implement a copy constructor and assignment operator for it. If you're using a C++11 conformant compiler it will also be good to also implement a move constructor and move assignment operator as well.
On the other hand, if you would like to not create a copy, you must either return a pointer or a reference to the member. You could also make the member a std::shared_ptr, which you may return in this case.
However, in your current implementation you're actually returning a shallow copy of NodeContainer. Once your copy goes out of scope its destructor is called, which deallocates its memory, which in this case is the original memory of your member, effectively making your member invalid. The implementation is not good as it is. So, depending on your goal, either implement the first advised solution, or the second.
I have a few classes that inherit the same class with a print method. I also have a custom-made dynamic array template class. I have created a few dynamic arrays of pointers to objects from the child classes. For every array I want to have a separate function for calling all the print methods of the objects pointed by the pointers- some times I want to print only the "weapons", sometimes only the "modifications" or sometimes everything. So far I have tried two solutions- copy-pasting the first method (as shown in the code) for every array or converting the dynamic arrays into arrays of pointers to the "mother" class and passing the new ones as an argument to an universal print function.
And here is some code:
class Item {...}
class Modification : public Item {...}
class Equipment : public Item {...}
DynamicArray<Modification*> modification;
DynamicArray<Equipment*> weapon;
//The first way:
void printModsInfo ()
{
if (modification.size() == 0)
cout<<"No mods in inventory\n";
else
for (int i = 0; i < modification.size(); i++)
modification.returnElement(i)->printInfo();
}
void printWeaponsInfo ()
{
if (weapon.size() == 0)
cout<<"No weapons in inventory\n";
else
for (int i = 0; i < weapon.size(); i++)
weapon.returnElement(i)->printInfo();
}
//The second way:
void _printModsInfo ()
{
Item** tempRef = new Item*[modification.size()];//array of pointers
for (int i = 0; i < modification.size(); i++)//converting DynamicArray<Modification*> into Item** tempRef
tempRef[i] = modification.returnElement(i);
printCertainStuffInInventory (tempRef, modification.size());
delete tempRef;
}
void _printWeaponsInfo ()
{
Item** tempRef = new Item*[weapon.size()];
for (int i = 0; i < weapon.size(); i++)
tempRef[i] = weapon.returnElement(i);
printCertainStuffInInventory (tempRef, weapon.size());
delete tempRef;
}
void printCertainStuff (Item** arr, int size)
{
if (size == 0)
cout<<"Nothing from this type in inventory...\n";
else
for (int i = 0; i < size; i++)
arr[i]->printInfo();
}
So I have two choices: copy-paste the five rows from the fist way, or copy-paste the more complicated five rows from the second way and add five more rows for the printing function. But what I really want to do is to simply pass the dynamic arrays as arguments and make the conversion (if needed) in the printing function- or to simply call the "printer" by writing: printCertainStuff(modification); (or "weapon" or whatever). And this is required by the design of the whole project. I did consult my teacher, but the answer was that there is no way to do that without converting before calling the function.
But still- is there a way to pass such dynamic arrays as arguments the way I want?
I'm not 100% clear on what you're wanting, but if it is to combine all your print methods you could try using a template:
template< class T >
void printInfo ( const T& arr, const char* failmessage )
{
if (arr.size() == 0)
cout<<failmessage;
else
for (int i = 0; i < arr.size(); i++)
arr.returnElement(i)->printInfo();
}
And then to use for weapons you'd go:
printInfo( weapon, "No weapons in inventory\n" );
And similarly for modifications.
I'm having an issue with a lot of memory leaks from a class I've created. The assignment is requires creating a word search puzzle on the heap. I've created my destructor, copy constructor and overload the assignment operator.
I think there must be something wrong with one of these functions, because the final check to ensure it is working is to create objects in a loop, to see if it fails and my function is crashing. I've tried different forms of the destructor and I've tried changing around the copy and assignment operator with no luck. Kind of at a loss, and the lack of warnings is really making it difficult to debug without a proper understanding of the heap.
Any help would be really appreciated!
Here are some functions that are working with the heap.
JumblePuzzle::~JumblePuzzle(){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete jumble;
}
JumblePuzzle::JumblePuzzle(string word, string diff){
int i = 0;
toHide = word;
difficulty = diff;
jumble = buildArray();
fillArray();
hideWord();
}
JumblePuzzle::JumblePuzzle(JumblePuzzle& temp){
size = temp.size;
rowPos = temp.rowPos;
colPos = temp.colPos;
direction = temp.direction;
toHide = temp.toHide;
difficulty = temp.difficulty;
jumble = temp.getJumble();
}
JumblePuzzle& JumblePuzzle::operator=(const JumblePuzzle& right){
if (this != &right){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete[] jumble;
size = right.size;
rowPos = right.rowPos;
colPos = right.colPos;
direction = right.direction;
toHide = right.toHide;
difficulty = right.difficulty;
jumble = right.getJumble();
}
return *this;
}
charArrayPtr* JumblePuzzle::buildArray() const{
charArrayPtr* array = new char*[size];
for (int i = 0; i < size; ++i){
array[i] = new char[size];
}
return array;
}
Here's the line its failing on.
int loopLimit =20;
for (int i = 0; i < loopLimit; i++)
JumblePuzzle jp("HIDDENWORD", "hard");
Thanks for any possible help!
EDIT:
Here is my .h file as well.
#ifndef JUMBLE_H_
#define JUMBLE_H_
#include <time.h>
#include <cstdlib>
#include <string>
using namespace std;
typedef char* charArrayPtr;
class BadJumbleException {
public:
BadJumbleException(const string&);
string& what();
private:
string message;
};
class JumblePuzzle{
public:
JumblePuzzle(string, string); //simple constructor
JumblePuzzle(JumblePuzzle&); //copy constructor
~JumblePuzzle(); //deconstructor
charArrayPtr* getJumble() const;
JumblePuzzle& operator=(const JumblePuzzle&);
//accessors
int getSize();
int getRowPos();
int getColPos();
char getDirection();
private:
//attributes
int size;
int rowPos;
int colPos;
char direction;
charArrayPtr* jumble;
string toHide;
string difficulty;
void fillArray();
void hideWord();
char randomDirection();
int randomNum(int);
charArrayPtr* buildArray() const;
};
#endif
and my getJumble. It's used to get the actual word search created. Returned a copy rather than the pointer so it cant be modified.
charArrayPtr* JumblePuzzle::getJumble() const{
charArrayPtr* tempJumble = new char*[size];
for (int i = 0; i < size; ++i){
tempJumble[i] = new char[size];
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++){
tempJumble[i][j] = jumble[i][j];
}
}
return tempJumble;
}
There is one major thing wrong with your code, and that is you failed to initialize the "size" member in the JumblePuzzle(string, string) constructor.
There are other things you should do:
1) Create a separate function to destroy the 2d array within the JumblePuzzle class. You seem to be copying the same loops to do this in multiple places. No need for that if you just call a function to do this work.
2) Your assignment and copy constructor are not exception safe. If new[] throws an exception during the creation of the copy, then the original object has invalidated data. In other words, you've destroyed the data, and when you want to create another 2d array, when new[] says "oops", you've destroyed your original data and can't get it back.