in this code why does the first("invNummer") is always 0, when I initializate it dynamically? When I do it as a static(two) it works.
class Computer {
private:
int invNummer;
char* osName;
int state; // 0 – aus, 1 - an
public:
Computer(int INV, char* OS, int st);
void info() {
cout << invNummer << " " << osName << " " << state << endl;
}
};
Computer::Computer(int INV, char* OS, int st)
: invNummer(INV)
, osName(OS)
, state(st)
{};
int main()
{
Computer* one;
one = new Computer(10, (char*)"Windows", 1);
delete one;
Computer two(9, (char*)"Linux", 0);
one->info();
two.info();
return 0;
}
Output looks like this:
0 Windows 1
9 Linux 0
As #It's_comming_home pointed out to you, your issue is not related to creating the one object dynamically, but to the deletion of that object:
delete one;
When you delete the one object, the pointer is left dangling, ie it is no longer usable. If you try to dereference it afterwards:
one->info();
You will get undefined behavior, like your output shows.
To fix this, just move the deletion of the one object after you invoke its info() method:
one->info();
two.info();
delete one;
Related
I'm learning C++. Now, I'm trying to make one sample related with overloading operators of an object. My object (called Contador) has different methods and variables which help user to count iterations.
Header file of the object:
class Contador
{
private:
int* Valor;
int* Salto;
public:
Contador(int Valor_Inicio = 0, int Salto = 1);
~Contador();
inline int Get_Valor() const { return *Valor; }
inline int Get_Salto() const { return *Salto; }
inline void Incremento() { Set_Valor(Get_Valor() + Get_Salto()); }
inline void operator++ () { Set_Valor(Get_Valor() + Get_Salto()); }
void Set_Valor(int Valor);
void Set_Salto(int Salto);
};
Cpp file of the object:
// Librerias Propias
#include "Contador.h"
Contador::Contador(int Valor_Inicio, int Salto)
{
Set_Valor(Valor_Inicio);
Set_Salto(Salto);
}
Contador::~Contador()
{
delete Contador::Valor;
delete Contador::Salto;
}
void Contador::Set_Valor(int Valor)
{
delete Contador::Valor;
Contador::Valor = new int(Valor);
}
void Contador::Set_Salto(int Salto)
{
delete Contador::Salto;
Contador::Salto = new int(Salto);
}
The main() function of the sample has 2 different for loops. In the first one, I call Incremento() method and in the second one I call the overloaded operator.
Main function:
void main()
{
// Genero el elemento de analisis.
Contador* contador = new Contador();
// Realizo el bucle con la función de incremento.
std::cout << "Incremento()" << std::endl;
for (contador->Set_Valor(0); contador->Get_Valor() < 3; contador->Incremento())
{
// Escribo algo.
std::cout << "Iteracion actual: " << contador->Get_Valor() << std::endl;
}
// Realizo el bucle on el operador sobrecargado
std::cout << "operador sobrecargado" << std::endl;
for (contador->Set_Valor(0); contador->Get_Valor() < 3; contador++)
{
// Escribo algo.
std::cout << "Iteracion actual: " << contador->Get_Valor() << std::endl;
}
}
The problem appears when main function passes the first iteration of the second loop. It throws one exception in Get_Valor() method.
It seems to me that it change the memory addres of the pointer Valorin some place, but I can`t find where.
Can anybody help me?
Thanks.
contador++ does not do what you think it does - contador is a pointer, not a Contador, so it will make contador point to something that does not exist.
You need to dereference the pointer.
However, *contador++ also increments contador - it is *(contador++) - and (*contador)++ does not compile because you have only overloaded the prefix operator (the postfix operator has the prototype operator++(int).
So, ++*contador will do what you want.
You can avoid many similar problems, and the clunky syntax, by not using pointers unnecessarily.
The expression contador++ increments the address that contador (a pointer) points to! So, after the first iteration, the pointer will be completely invalid.
To call the increment operator, you need: ++(*contador) which first dereferences the pointer to the object pointed to, then effects that object's increment operator.
3 coding issues:
main shoudl return int.
Valor and Salto are not initialized in constructor.
Contador::Set_Valor and Contador::Set_Salto requires initialized pointers (as you delete them).
Easy fix is:
class Contador
{
private:
int* Valor = nullptr;
int* Salto = nullptr;
//...
};
Last issue is in your last loop:
for (contador->Set_Valor(0); contador->Get_Valor() < 3; contador++)
As condator is a pointer (not pointing on an array), accessing condator[1] would be UB.
You wanted ++(*condator) (operator++ () is pre-increment whereas operator++ (int) is post-increment).
Finally, avoiding usage of all those pointers would simplify code (and no bother with rule of 3 you break):
class Contador
{
private:
int Valor;
int Salto;
public:
Contador(int Valor = 0, int Salto = 1) : Valor(Valor), Salto(Salto) {}
~Contador() = default;
int Get_Valor() const { return Valor; }
int Get_Salto() const { return Salto; }
void Incremento() { Set_Valor(Get_Valor() + Get_Salto()); }
void operator++ () { Set_Valor(Get_Valor() + Get_Salto()); }
void Set_Valor(int Valor) { this->Valor = Valor;}
void Set_Salto(int Salto) { this->Salto = Salto;}
};
int main()
{
Contador contador;
std::cout << "Incremento()" << std::endl;
for (contador.Set_Valor(0); contador.Get_Valor() < 3; contador.Incremento())
{
std::cout << "Iteracion actual: " << contador.Get_Valor() << std::endl;
}
std::cout << "operador sobrecargado" << std::endl;
for (contador.Set_Valor(0); contador.Get_Valor() < 3; ++contador)
{
std::cout << "Iteracion actual: " << contador.Get_Valor() << std::endl;
}
}
In addition to previous answers.
As I could see Contador* contador = new Contador(); code also contains UB (undefined behaviour)
This call is equal to constructor with parameters Contador(0, 1)
which will do Set_Valor and Set_Salto which call delete first but at this moment content of this variables is not guaranteed to be nullptr so you might corrupt data. Also compiler if it sees UB might optimize out all other code since it's already UB and it can change behaviour anyway it wants for example throw it away completely. https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=633
Currently working on Object Oriented Programming in c++ and having problems with an instance showing nothing changed from a method I've created.
The whole code is based off of this object I've created from a header file.
#ifndef DEQUE_H_
#define DEQUE_H_
#include <iostream>
const int CAPACITY = 5;
const int DEFAULT = -1;
class Deque
{
public:
Deque();
int get_size() const;
bool is_empty() const;
bool is_full() const;
int operator[](int i) const;
static Deque insert_tail(int);
private:
int size_;
static int array_[CAPACITY];
};
std::ostream & operator<<(std::ostream &, const Deque &);
#endif
One of the problems I'm having is the insert_tail method that doesn't show any changes to my static array.
In the cpp file itself.. these are the function declarations.
#
include <iostream>
#include "Deque.h"
Deque::Deque()
:size_(0)
{
}
int Deque::array_[5] = {};
int Deque::get_size() const
{
return size_;
}
bool Deque::is_full() const
{
if (size_ == 5) return 1;
else return 0;
}
bool Deque::is_empty() const
{
if (size_!= 5) return 1;
else return 0;
}
int Deque::operator[](int i) const
{
int something = array_[i];
return something;
}
Deque Deque::insert_tail(int x)
{
Deque d;
d.size_ += 1;
int size = d.size_;
d.array_[size - 1] = x;
return d;
}
std::ostream & operator<<(std::ostream & cout, const Deque & dq)
{
cout << dq.get_size() << " [ ";
for (int i = 0; i < dq.get_size(); ++i)
{
cout << dq[i] << " ";
}
cout << "]";
return cout;
}
The operator works just fine. The bools work just fine and the remove_head and remove_tail thing I'll do once I figure out insert tail. Right now, it's not making any chances to the very object I've created inside the main.
#include <iostream>
#include "Deque.h"
void print(const Deque & deque)
{
static int i = 1;
std::cout << i << ". " << deque << ", empty: " << deque.is_empty()
<< ", full: " << deque.is_full();
i++;
}
void test_insert_tail(Deque & deque, int x)
{
deque.insert_tail(x);
print(deque); std::cout << "\n";
}
int main()
{
Deque deque;
print(deque);
std::cout << "\n";
test_insert_tail(deque, 2);
return 0;
}
The output should look like this,
1. 1 [ 2 ], empty: 0, full: 0
but looks like this
1. 0 [], empty: 1, full: 0
What's going on inside my static method for handling all the private attributes that I'm missing on? What did I do wrong exactly?
The problem with your code is the misuse of the static word. In fact, static means that is not associated with an instance of the object: this means that the content of the static member (the array_ variable in this case) is shared between every instance you will create.
That's the same for the insert_tail method, that can be used even if you don't create an instance. Now, let's try to understand what you've written in this method:
Deque d;
d.size_ += 1;
int size = d.size_;
d.array_[size - 1] = x;
return d;
In the first line, you created a new Deque object. That's the first mistake, cause you're not modifying the actual Deque. Then you add the operations, and in the end, you return the created Deque. However, this object is not saved anywhere, because when you call deque.insert_tail() you aren't assigning the returned value anywhere.
Let's try and get this a little bit more concrete.
Since what you're doing is creating a data structure, you won't need any static member. This because everything needs to be saved inside the data structure.
Then, inside the insert_tail you'll need to remove the object you created inside. It'll look something like this:
size_ += 1;
int size = size_;
array_[size - 1] = x;
With those two modifications the code will probably work as expected, however, I suggest you focus on improving the appearance of your code. Using the underscore character at the end of the variable name is a little bit confusing. In C the only scenario you can use it inside the name int foo_bar for normal variables, and at the beginning int _foo for reserved variables.
I'm trying to implement stacks using constructors in C++. I'm required to use an external function to push an element on the stack, however, it doesn't seem to work properly. The pushexternal function seems to "enter" the push function, but it doesn't increase the ind value, therefore it doesn't add a new element onto the stack (for example in my code, all pushxternals will try to push a value onto the same index, the last one used by s.push - ind==2). I'm not sure what I'm doing wrong.
Oh, I'm only supposed to modify the class code - the pushexternal and main have to remain unchanged.
#include <iostream>
using namespace std;
class Stack {
public:
int ind;
int * arr;
Stack()
{
arr = new int[25];
ind = -1;
}
~Stack()
{
delete [] arr;
}
void push(int val)
{
arr[++ind] = val;
cout << "Added " << arr[ind] << " to " << ind << endl;
}
void top()
{
cout << "Last: " << arr[ind];
}
};
void pushexternal(Stack s, int a) {
s.push(a);
}
int main() {
Stack s;
s.push(0);
s.push(1);
s.push(2);
pushexternal(s, 3);
pushexternal(s, 4);
pushexternal(s, 5);
return 0;
}
Results:
Added 0 to 0
Added 1 to 1
Added 2 to 2
Added 3 to 3
Added 4 to 3
Added 5 to 3
Top: 2
void pushexternal(Stack s, int a) {
s.push(a);
}
receives a Stack as a parameter, which means it receives an object which is a copy of your object.
You should operate on references, this way you will not send a copy of the object to be manipulated, but the reference of the object, thus the original object will be manipulated.
void pushexternal(Stack s, int a) {
s.push(a);
}
You are passing the Stack object to this function by value, not by reference. This makes a temporary copy of the original Stack object, so the original object remains unchanged. Not to mention that this will result in memory corruption, since the RAII principle has been violated.
Just by the luck of the draw, I guess, your code is not segfaulting.
I'm having the weird crashing that occurs everytime it goes to the for loop to initialize each position to undefined. Can anyone shine light on why this is happening?
#include
#include
#include
using namespace std;
class MyPhoneBook
{
public:
MyPhoneBook(int, string, string, string, string);
MyPhoneBook();
~MyPhoneBook();
void initialise(int, int, string, string, string, string);
bool search(string&, int);
bool find_free_pos();
void add();
void remove();
void display(int);
friend istream& operator >> (istream& in, MyPhoneBook& ph);
friend ostream& operator << (ostream& out, MyPhoneBook& ph);
private:
int *recordid;
int *status; // -1 is no longer at this number, 0 is blocked, 1 is not blocked, 2 is free
string *name, *areacode, *number, *group;
};
int main(int argc, char** argv)
{
cout << "test 1" << endl;
MyPhoneBook *myphbk; // pointer that will point to an object of a MyPhoneBook class
myphbk = new MyPhoneBook[100]; // now its using dynamic memory
cout << "test 2" << endl; //just for testing
int pos = 0;
for(pos = 0; pos < 100; pos++) // initializing everything to undefined, and position to free (position is the second parameter sended in)
{
myphbk[pos].initialise( (pos+1) , 2 , "Undefined" , "Undefined" , "Undefined" , "Undefined");
}
cout << "test 3" << endl; //just for testing
}
return 0;
void MyPhoneBook::initialise(int recordid_,int status_, string name_, string areacode_, string number_, string group_)
{
//now assign them to private member variables
*recordid = recordid_;
*status = status_;
*name = name_;
*areacode = areacode_;
*number = number_;
*group = group_;
//end of assigning
}
does anyone have any idea why can't my program reach the cout << "test 3" << endl part of the program without crashing?
Since you did not paste the constructor of MyPhoneBook i can only guess, but the problem could be the lines
*recordid = recordid_;
*status = status_;
if you did not assign a valid address to recordid and status in the constructor, e.g. by
recordid = new int;
status = new int;
You might want to declare those member variables as a simple int.
I call this code in main()
for (COwnerList l=b1.ListOwners(10); !l.AtEnd(); l.Next())
cout << l.Surname() << ", " << l.Name () << endl;
for (CCarList l=b1.ListCars("Peter","Smith"); !l.AtEnd(); l.Next ())
cout << l.RZ () << ", " << l.VIN() << endl;
for (COwnerList l=b1.ListOwners(10); !l.AtEnd(); l.Next())
cout << l.Surname() << ", " << l.Name() << endl;
I tried to debug and found out seg fault comes from Constructor of COwnerList
COwnerList CRegister::ListOwners (unsigned int vin) const
{
vector<Car>::const_iterator it;
COwnerList tmp;
it = lower_bound(byVINList.begin(), byVINList.end(), Car("",vin), cmpVIN);
if(it != byVINList.end())
tmp.car = &(*it);
tmp.in = it->owners.end() - it->owners.begin();
return tmp;
}
constructor im calling looks like this:
COwnerList::COwnerList(void)
{
here = car->owners.begin();
i = 0;
in = car->owners.end() - car->owners.begin();
}
interesting is it doesnt crash after 1st for in main(), so there must be something wrong in the code between those 2 for cycles in main(), but i have no idea what it could be i am not modifying anything related to ListOwners() there
EDIT1
Car constructor:
Car::Car( const string & pid,
const unsigned int & pvin = 0,
const string & cname = "",
const string & csurname = "")
{
rz = pid;
VIN = pvin;
name = cname;
surname = csurname;
}
EDIT2
class COwnerList
{
public:
COwnerList(void);
string Name ( void ) const;
string Surname ( void ) const;
bool AtEnd ( void ) const;
void Next ( void );
//vector<pair<string, string> > powners;
const Car *car;
int in;
private:
vector<pair<string, string> >::const_iterator here;
int i;
};
The problem is that the car pointer is not initialized during the call in the COwnerList constructor. In the first loop, you might have got lucky. Things like this happens all the time. Sometimes the OS won't throw a seg fault everytime when you are calling a code which is not allocated yet.
Just put a condition guard in your code like this:
if (car != NULL) {
here = car->owners.begin();
i = 0;
in = car->owners.end() - car->owners.begin();
}
The error is more likely you are modifying the vector after saving that tmp.toto pointer to the vector's internal storage.
Note that when you do tmp.car = &(*it) you are making a pointer towards the internal storage of the vector.
If later you call push_back() on the vector, you cannot rely in the pointers that you had before, because the vector can reallocate its contents in other memory addresses after you call the push_* methods.
Also note that a debugger may not tell the exact line that has to be corrected, even if the crash happens there. The debugger may tell you the first line where the problem is evident, but the cause of the problem may have happened several lines before.