Адрес памяти вместо значения в 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;
  }

}
Другие вопросы по тегам