Adding new objects to dynamic array - c++

I am trying to write function to add objects name Hotel to dynamically allocated array. Problem is, while my code can add the first one, it fails to add anything further than that. Here is the code responsible for adding new objects.
void HotelReservationSystem::addHotel( const std::string name, const int numFloors, const int *numRooms)
{
if ( hotelNum == 0 && hotels == NULL){
hotels = new Hotel[1];
Hotel hotelA ( name, numFloors, numRooms);
hotels[0] = hotelA;
hotelNum++;
std::cout << "Hotel " << name << " is added." << std::endl;
return;
}
for (int x = 0; x < hotelNum; x++){
if ( name == hotels[x].getName())
std::cout << "\n" << "Hotel " << name << " already exists." << std::endl;
return;
}
Hotel* temp = new Hotel[hotelNum+1];
for ( int x = 0; x < hotelNum; x++){
temp[x] = hotels[x];
}
temp[hotelNum] = Hotel ( name, numFloors, numRooms);
delete [] hotels;
hotels = temp;
hotelNum++;
std::cout << "Hotel " << name << " is added." << std::endl;
}
So far i cant detect anything wrong with this code.

for (int x = 0; x < hotelNum; x++){
if ( name == hotels[x].getName())
std::cout << "\n" << "Hotel " << name << " already exists." << std::endl;
return;
}
Here, the return is not part of the if statement. Your code will just return in the first iteration. You need to put braces around those two lines.
Of course, as the comments say, you shouldn't be doing memory management like this yourself. Use std::vector instead. Your function would become only a few lines.

You don't seem to have any declaration for the variable "hotels".

Related

Variable inside a loop being set to the next array's element has the same memory address all the time? [duplicate]

This question already has answers here:
Why is the address of a variable defined inside a loop unchanged on each iteration?
(3 answers)
Closed 2 years ago.
Let's consider a little program like this:
#include <iostream>
using namespace std;
typedef struct
{
int i, j, k;
} ThreeDPoint;
int main() {
ThreeDPoint p[10];
for (int i = 0; i < 10; i++) {
p[i].i = i * 3;
p[i].j = i * 3 + 1;
p[i].k = i * 3 + 2;
}
for (int i = 0; i < 10; i++) {
cout << "i = " << i << endl;
ThreeDPoint lp = p[i];
cout << "&p[" << i << "] = " << (long) &lp << endl;
cout << "&p[" << i << "].i = " << (long) &lp.i << endl;
cout << "p[" << i << "].i = " << (long) lp.i << endl;
cout << "&p[" << i << "].j = " << (long) &lp.j << endl;
cout << "p[" << i << "].j = " << (long) lp.j << endl;
cout << "&p[" << i << "].k = " << (long) &lp.k << endl;
cout << "p[" << i << "].k = " << (long) lp.k << endl;
}
}
Variable named lp is updated to have a value of a structure inside an array and being updated with the i variable inside the loop. I expect that if, for instance, first element (p[0]) starts at memory location 100, then the second element (p[1]) will start from 112, assuming that sizeof(int) == 4 is true.
It is not the case, though: the printed value informs that the variable is actually updated to contain the next structure value all the time, but it seems that it, for some reason, has the same memory address (for i = 0 &p[i].i == 100, for i = 1 &p[i].i == 100, too). What's interesting is that if the intermediate variable lp is removed and p[i] is accessed directly, then I see the expected memory addresses to be printed out (for i = 0 &p[i].i == 100, for i = 1 &p[i].i == 112). Here are the logs:
i = 0
&p[0] = 140736159721040
&p[0].i = 140736159721040
p[0].i = 0
&p[0].j = 140736159721044
p[0].j = 1
&p[0].k = 140736159721048
p[0].k = 2
i = 1
&p[1] = 140736159721040
&p[1].i = 140736159721040
p[1].i = 3
&p[1].j = 140736159721044
p[1].j = 4
&p[1].k = 140736159721048
p[1].k = 5
i = 2
&p[2] = 140736159721040
&p[2].i = 140736159721040
p[2].i = 6
&p[2].j = 140736159721044
p[2].j = 7
&p[2].k = 140736159721048
p[2].k = 8
Why is that? Why is the value updated but the memory location is the same? Is this some kind of g++ optimization that is performed after variables usage analysis?
You are printing the address of the variable, not the address of your array elements. The variable and the array don't have the same address (obviously) and it's quite reasonable (but not guaranteed) that the same address would be reused for the variable each time around the loop.
To print the address of the array element try this
cout << "&p[" << i << "] = " << &p[i] << endl;
I guess your misunderstanding is that you think
ThreeDPoint lp = p[i];
somehow makes lp point to the array element. But it doesn't, it copies the array element and stores a copy in the variable.

Output value of array rather than memory address of array

So I've made a basic polynomial class in C++ which stores the coefficients of these polynomials dynamically on the heap. I'm currently in the process of overloading operators so that I can add/subtract polynomials together in order to simplify them etc.
However I'm getting unexpected results when I try to overload the * operator. It looks like instead of returning the value of an index in the array it is returning the position of the array.
This is my *operator method in my .cpp file:
Polynomial Polynomial::operator*(Polynomial p) {
int maxDegree = (degree)+(p.degree - 1);
int *intArray3 = new int[maxDegree];
int i, j;
for (int i = 0; i < degree; i++) {
for (int j = 0; j < p.degree; j++) {
cout << getCoef(i) << " * " << p.getCoef(j) << " = " << getCoef(i)*p.getCoef(j) << endl;
intArray3[j] += (getCoef(i))*(p.getCoef(j));
cout << " intArray3[" << j << "] contains : " << intArray3[j] << endl;
}
}
return Polynomial(maxDegree, intArray3);}
The lines:
cout << getCoef(i) << " * " << p.getCoef(j) << " = " << getCoef(i)*p.getCoef(j) << endl;
and
cout << " intArray3[" << j << "] contains : " << intArray3[j] << endl;
return
10 * 1 = 10
intArray3[0] contains : -842150441
in my console. I'm assuming that the problem lies with my use of pointers somewhere but I can't for the life of me think why. I implemented this overload in a similar way to my + and - overloads and they work fine. Any assistance would be greatly appreciated. Cheers.

How can I get the size of a vector that is inside another vector?

I'm having trouble getting the size of a vector by dot-walking from a parent vector into the one in question. I have verified that calling the function myfunc 1 2 3 4 5 creates five Person objects and puts them in the left vector. But when I try to get that same size to return by dot-walking from bridge to left, I get 0 as the size.
What am I doing wrong?
int main(int argc, char* argv[]) {
Person* p_ptr;
int id_source = 0;
vector<Person> left;
vector<Person> right;
bridge.push_back(left);
bridge.push_back(right);
cout << "bridge.size() = " << bridge.size() << endl;
for (int i = 1; i < argc; i++) {
id_source++;
cout << "Creating Person with crossing speed of " << argv[i] << " and id of " << id_source << endl;
p_ptr = new Person(atoi(argv[i]), id_source);
left.push_back(*p_ptr);
}
/*SIZE TESTING*/
cout << "Left side of bridge has " << left.size() << " people on it " << endl;
cout << "bridge.at(0).size() = " << bridge.at(0).size() << endl;
cout << "bridge.at(1).size() = " << bridge.at(1).size() << endl;
int slowest_id = get_slowest(0);
for (int i = 0; i < left.size(); i++) {
if (slowest_id == left.at(i).get_id()) {
p_ptr = &left.at(i);
}
}
cout << "The slowest person has id of " << slowest_id << " and speed of " << p_ptr->get_crossing_time() << endl;
}
}
left and bridge[0] are two different lists. When you call bridge.push_back(left) you make a copy of the current left list (which is empty). Elements added later will not be in the bridge version.

Heap Leak in a cpp code

I am doing a project named wireless Network Toplogy. It use graphs as a data structure. I have make pointers but am facing heap leak problems. Please can anyone help fix this error? Where to call the delete operator? The cpp code is attached:
#include <string>
#include <ctime>
#include <cstdlib>
#include <iostream>
#include "myGraph.h"
#include "wirelessNetwork.h"
using namespace std;
void main()
{
srand(time(NULL));
/* First part of the experiments */
for (int i = 500; i <= 950; i += 50)
{
wirelessNetwork *g = new wirelessNetwork(10, i);
std::cout << (L"For network with n=") << i << (L": ") << std::endl;
double average = (static_cast<double>(g->graph->numEdges) / (static_cast<double>(g->graph->numVertices)));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
/* Perform topology control */
g->topologyControl();
std::cout << (L" After topology control: ") << std::endl;
average = (static_cast<double>(g->graph->numEdges)) / (static_cast<double>(g->graph->numVertices));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
std::cout << std::endl;
}
/* Second part of the experiments */
wirelessNetwork *g = new wirelessNetwork(10, 1000);
std::cout << (L"***********************************") << std::endl;
for (int i = 1; i <= 10; i++)
{
/* Randomly pick two vertices as the source and destination */
int i1 = static_cast<int>(1000 * rand());
int i2 = static_cast<int>(1000 * rand());
string nameTemp = "a";
string node1 = nameTemp + std::to_string(i1);
string node2 = nameTemp + std::to_string(i2);
//ORIGINAL LINE: String[] route = g.compassRouting(node1, node2);
string *route = g->compassRouting(node1, node2);
std::cout << std::endl;
std::cout << (L"Path generated from ") << node1 << (L" to ") << node2 << (L":") << std::endl;
for (int k = 0; k < route->length(); k++)
{
std::cout << (L" ") << route[k];
}
if (node2 != route[route->length() - 1])
{
std::cout << std::endl;
std::cout << (L" No route found...") << std::endl;
}
std::cout << std::endl;
std::cout << (L" Length of the path generated is ") << (route->length() - 1) << std::endl;
}
/* Third part of the experiments */
g->topologyControl();
std::cout << std::endl;
std::cout << (L"***********************************") << std::endl;
std::cout << (L"After topology control...") << std::endl;
for (int i = 1; i <= 10; i++)
{
int i1 = static_cast<int>(1000 * rand());
int i2 = static_cast<int>(1000 * rand());
string nameTemp = "a";
string node1 = nameTemp + std::to_string(i1);
string node2 = nameTemp + std::to_string(i2);
//ORIGINAL LINE: String[] route = g.compassRouting(node1, node2);
string *route = g->compassRouting(node1, node2);
std::cout << std::endl;
std::cout << (L"Path generated from ") << node1 << (L" to ") << node2 << (L":") << std::endl;
for (int k = 0; k < route->length(); k++)
{
std::cout << (L" ") << route[k];
}
if (node2 != route[route->length() - 1])
{
std::cout << std::endl;
std::cout << (L" No route found...");
}
std::cout << std::endl;
std::cout << (L" Length of the path is ") << (route->length() - 1) << std::endl;
}
}
`
One way of identifying when to call delete operator is to check when that pointer variable goes out of scope and to delete it just before it goes out of scope.
void func()
{
ClassA* ptr1 = new ClassA;
//do NULL check for ptr1 and do stuff
delete ptr1;
//here ptr1 will lose scope.
//If not deleted, it will become a memory leak.
}
There can be scenarios where we cannot delete a pointer even if it goes out of scope. For example if we store the new pointer value in some other pointer variable, and the 2nd variable is still not out of scope.
void func(bool IsReady)
{
ClassA* ptr1 = NULL;
if(IsReady)
{
ClassA* ptr2 = new ClassA;
//do stuff
ptr1 = ptr2;
//in this case, even though ptr2 will lose scope outside this block,
//the ptr2 value is assigned to ptr1 which is does not lose scope outside this block.
}
//here ptr1 will still contain the data we copied in the if block,
//else it will be NULL. After use of ptr1 is complete, do a NULL check and delete.
if(ptr1 != NULL)
delete ptr1;
}
In your case I see only the first type, and only 2 places the new operator is called.
Have called the delete operator at the appropriate place for the first case, just before g goes out of scope:
/* First part of the experiments */
for (int i = 500; i <= 950; i += 50)
{
wirelessNetwork *g = new wirelessNetwork(10, i);
std::cout << (L"For network with n=") << i << (L": ") << std::endl;
double average = (static_cast<double>(g->graph->numEdges) / (static_cast<double>(g->graph->numVertices)));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
/* Perform topology control */
g->topologyControl();
std::cout << (L" After topology control: ") << std::endl;
average = (static_cast<double>(g->graph->numEdges)) / (static_cast<double>(g->graph->numVertices));
std::cout << (L" The average degree is ") << average << std::endl;
std::cout << (L" The maximum degree is ") << g->getMaxDegree() << std::endl;
std::cout << std::endl;
//here g loses scope and does not seem to be stored in any other pointer
delete g;
}
For the second case, call delete at the end of the function.
Hope this solves your issue of when to call the delete in your code.
However, you can avoid calling both new and delete in your case by replacing:
wirelessNetwork *g = new wirelessNetwork(10, i);
with
wirelessNetwork g(10, i);
And for accessing the member variables use g. instead of g->.
For example: g->topologyControl(); should be g.topologyControl();
Hope this answer helps.
The best answer is you shouldn't be using pointers or the new operator. As others suggested, just construct the object directly in the scope where it is needed, so it will be destroyed automatically when it goes out of scope.
A very common (but I think very poor) answer to this question, is to delete the object immediately before the pointer goes out of scope and/or put all your delete operations at the same nesting level as the corresponding new operations. As in this case, when that approach is practical, you almost always didn't need the pointer or the new at all. When it is not practical for the lifetime of the object to match the scope in which it is created, then you really need a pointer and use of the new operator and managing the lifetime of the object is one of the harder aspects of C++ programming. There are no generic answers in those cases. But until you have such a problem, don't create it by pointless use of the new operator.

Memory location for a pointer passed in a function gets deleted [duplicate]

This question already has answers here:
Pointer errors in the method of transmission(c++)
(4 answers)
Closed 8 years ago.
Question: I can't seem to set a pointer to an address that was created inside of a function. It always gets set to Null, how do I fix this?
Problem: I believe the problem is caused by the variable being created inside of another function. What's happening is that after the function executes, the pointer is set to NULL again.
Code:
void listAdd(int *list, int &length) {
int* tempList = new int[ length + 1 ];
for( int i = 0; i < length; i ++ )
{
(tempList)[ i ] = (list)[ i ];
}
cout << " Previous adress: " << hex << list << endl;
if ( list != NULL )
delete[] list;
list = new int[ length + 1 ];
cout << " New address: " << hex << list << endl << dec;
for( int i = 0; i < length; i ++ )
{
(list)[ i ] = (tempList)[ i ];
}
delete[] tempList;
cout << " Enter a number: ";
int stored = 0;
cin >> stored;
(list)[length -1] = stored;
length ++;
cout << " Length: " << length << "\n";
cout << " value at array point 0: " << (list)[length -1];
cout << "\n retry " << (list)[length-1] <<"\n";
cout << "\n \n \n This is pointing to 0x" << hex << list << '\n' << flush;
}
It seems you would like the changes to list to be valid after the function returned: since list is passed by value, the object manipulated inside the function happens to be a copy of the one you passed in. You probably either want to pass the object by reference, i.e.:
void listAdd(int*& list, int &length) {
// ...
}
... or return the result
int* listAdd(int* list, int& length) {
// ...
return list;
}
list = listAdd(list, length);
Well, realistically, you really really want to encapsulate the objects in a class or just use std::vector<int>.