Адрес памяти вместо значения в cout класса
Я пытаюсь написать собственную простую реализацию списка форвардов. Я хотел бы получить доступ к элементу по cout << list[0]. Я написал следующий код, но вместо значения я получил что-то вроде x637c00539997. Что я сделал не так? Что еще я могу улучшить в своем коде?
#include <iostream>
#include <assert.h>
#include <cstdio>
#include <cstring>
#include <memory>
using namespace std;
class myList{
public:
class myListExceptionEmpty: public exception
{
public:
virtual const char* what() const throw()
{
return "EMPTY";
}
};
void push_back(int valve);
int getSize();
bool isEmpty();
void removeFirst();
void remove(int x);
void dump();
void pop_front();
struct elem
{
std::shared_ptr<elem> next;
int val;
};
class proxy
{
public:
std::shared_ptr<myList::elem> position;
proxy(std::shared_ptr<myList::elem> pos)
{
position = pos;
}
};
std::shared_ptr<myList::proxy> operator[](int position);
private:
std::shared_ptr<elem> start;
std::shared_ptr<elem> getLastElement();
std::shared_ptr<proxy> current;
int size = 0;
};
ostream& operator<<(std::ostream& os, myList::proxy& obj)
{
os << obj.position->val;
return os;
}
shared_ptr<myList::proxy> myList::operator[](int position)
{
std::shared_ptr<elem> p = start;
for(int i=0;i<position;i++)
{
p = p->next;
if (p == NULL) throw std::out_of_range("out");
}
//cout << p->val;
std::shared_ptr<proxy> tmp(new myList::proxy(p));
current = tmp;
return current;
}
std::shared_ptr<myList::elem> myList::getLastElement()
{
std::shared_ptr<elem> p = start;
while(p->next != NULL ) p = p->next;
return p;
}
bool myList::isEmpty()
{
return size;
}
void myList::dump()
{
std::shared_ptr<elem> x = start;
while (x != NULL)
{
cout << x->val << endl;
x = x->next;
}
}
void myList::push_back(int valve)
{
std::shared_ptr<elem> p, n(new elem());
n->next = NULL;
n->val = valve;
p = start;
if(p != NULL)
{
while(p->next != NULL ) p = p->next;
p->next = n;
}
else start = n;
size++;
}
void myList::remove(int x)
{
if (size == 0) throw myListExceptionEmpty();
std::shared_ptr<elem> p, prv;
p = start;
while(p->next != NULL)
{
if (p->val == x)
{
prv->next = p->next;
size--;
}
prv = p;
p = p->next;
}
}
void myList::pop_front()
{
if (size == 0) throw myListExceptionEmpty();
std::shared_ptr<elem> p, prv;
p = start;
while(p->next != NULL)
{
prv = p;
p = p->next;
}
prv->next = NULL;
}
void myList::removeFirst()
{
if (size == 0) throw myListExceptionEmpty();
std::shared_ptr<elem> p;
p = start;
cout << start->val << endl;
if(p!= NULL)
{
start = p->next;
}
size--;
}
int myList::getSize()
{
return size;
}
int main()
{
myList array;
int size;
cin >> size;
char a;
int tmp;
for (int i=0; i<size; ++i) {
std::cin >> a;
if (a == 'D')
{
try{
array.removeFirst();
}
catch (myList::myListExceptionEmpty &e)
{
cout << e.what() << endl;
}
}
else if (a == 'A')
{
int tmp;
std::cin >> tmp;
array.push_back(tmp);
cout << "elem" << array[0];
}
else if (a == 'S') cout /*<< "Size:"*/ << array.getSize() << endl;
}
}
2 ответа
Что касается вопроса "что еще улучшить":
- Вы используете общие указатели, отлично! Вместо того, чтобы использовать
new
использовать соответствующую процедуруmake_shared
(см. документацию C++). - Не определяйте классы в классах. Пусть каждый класс имеет свой собственный заголовок и исходный файл. Это значительно повышает удобочитаемость, и даже компиляция выполняется быстрее, разбивая все классы на разные файлы (лучший способ: используйте include guard). Таким образом, вы также можете оставить пространство имен, как
myList::elem
, - использование
<cassert>
вместо<assert.h>
, В любом случае, вы используете C++11, так зачем использовать старую C-библиотеку?! - Просто пример: изменение
void myList::remove(int x)
вvoid myList::remove(const int& x)
, Пусть компилятор знает, чтоx
это объект только для чтения. Не вызывайте конструктор int-copy здесь (также в других строках кода).
Что касается вашего второго вопроса: ваш перегруженный оператор []
возвращает разделяемый указатель, а не объект, на который указывает указатель. Таким образом, он напечатает адрес указателя.
Это программа после исправления. Я использовал cout << *array[0]; вместо cout << array[0];. Чем тебе за помощь
#include <iostream>
#include <memory>
using namespace std;
class MyListProxy;
class MyListExceptionEmpty: public exception
{
public:
virtual const char* what() const throw(){
return "EMPTY";
}
};
class MyList{
public:
void push_back(int valve);
int getSize() { return size; };
bool empty() { return size; };
void removeFirst();
void remove(const int& x);
void dump();
void pop_front();
void clear() {this->start = NULL; size = 0;}
struct elem
{
shared_ptr<elem> next;
int val;
};
shared_ptr<MyListProxy> operator[](int position);
private:
shared_ptr<elem> start;
shared_ptr<MyListProxy> current;
shared_ptr<elem> getEnd();
int size = 0;
};
class MyListProxy
{
public:
shared_ptr<MyList::elem> position;
MyListProxy(shared_ptr<MyList::elem> pos)
{
position = pos;
}
};
ostream& operator<<(ostream& os, MyListProxy& obj)
{
os << obj.position->val;
return os;
}
shared_ptr<MyListProxy> MyList::operator[](int position)
{
if (start == NULL) throw out_of_range("out");
shared_ptr<elem> p = start;
for(int i=0;i<position;i++){
p = p->next;
if (p == NULL) throw out_of_range("out");
}
return make_shared <MyListProxy>(p);
}
shared_ptr<MyList::elem> MyList::getEnd()
{
if (start == NULL) return start;
shared_ptr<elem> p = start;
while(p->next != NULL ) p = p->next;
return p->next;
}
void MyList::dump()
{
shared_ptr<elem> x = start;
while (x != NULL)
{
cout << x->val << endl;
x = x->next;
}
}
void MyList::push_back(int valve)
{
shared_ptr<elem> p;
auto last = this->getEnd();
auto a = make_shared<elem>();
last = a;
last->val = valve;
size++;
}
void MyList::remove(const int& x)
{
if (size == 0) throw MyListExceptionEmpty();
shared_ptr<elem> p, prv;
p = start;
while(p->next != NULL)
{
if (p->val == x)
{
prv->next = p->next;
size--;
}
prv = p;
p = p->next;
}
}
void MyList::pop_front()
{
if (size == 0) throw MyListExceptionEmpty();
start = start->next;
}
int main()
{
MyList array;
int size;
cin >> size;
char a;
int tmp;
for (int i=0; i<size; ++i) {
cin >> a;
if (a == 'D')
{
try{
cout << *array[0];
array.pop_front();
}
catch (MyListExceptionEmpty &e)
{
cout << "EMPTY" << endl;
}
catch (out_of_range &e)
{
cout << "EMPTY" << endl;
}
}
else if (a == 'A')
{
int tmp;
cin >> tmp;
array.push_back(tmp);
}
else if (a == 'S') cout /*<< "Size:"*/ << array.getSize() << endl;
cout << "SIZE::" << array.getSize() << endl;
}
}