изменение идентификатора метода подкачки общего указателя - PullRequest
0 голосов
/ 03 февраля 2019

Предыстория: я не знаю, что заставило меня поэкспериментировать с этим, но я пытаюсь протестировать связанный список контейнеров, который внутренне использует smartpointers.

Вот ссылка repl: https://repl.it/@BasavarajNagar/GoodnaturedGlisteningSection-1

#include <memory>

using namespace std;

template<typename T>
class linkedlist {
  private:

  class node {
    public:
      T data;
      shared_ptr<node> next;
      node(T data) {
        this->data = data;
      }
  };

  // non const unique ptr
  shared_ptr<node> head;

  public:
  void add(T data) {
    cout<< "adding " << endl;// + data << endl;

    if (head == nullptr) {
      head = shared_ptr<node>(new node(data));
      return;
    }

    shared_ptr<node> cursor;
    cursor.swap(head);

    // this works well
    while (cursor != nullptr) {
      cout << cursor->data << endl;
      cursor = cursor->next;
    }
    cout << data << endl;
    // this is the problematic assignment
    cursor = shared_ptr<node>(new node(data));
  }

  void trace() {
    shared_ptr<node> cursor;
    cursor.swap(head);

    cout << "trace" << endl;
    while (cursor != nullptr) {
      cout << cursor->data << endl;
      cursor = cursor->next;
    }
  }
};

int main() {
  std::cout << "Hello World!\n";

  linkedlist<int> ll;
  ll.add(22);
  ll.add(45);
  ll.add(63);
  ll.trace();

}

Метод трассировки всегда указывает на последний элемент, заголовок теряется после перестановки во время метода добавления.

Примечание. Я знаю, что это не код качества производства, а понимание внутренних особенностей / особенностей.умных указателей.Поэтому, пожалуйста, избегайте комментариев по качеству кода.

1 Ответ

0 голосов
/ 03 февраля 2019

Вы плохо понимаете общие указатели.https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr

Информация трассировки, которая вам нужна больше всего, это node :: node и node :: ~ node.Отслеживание, когда фактические узлы будут созданы и уничтожены, поможет вам.Вы также должны понимать сферу.

Быстрая критика вашей функции "добавления" (исправления, оставленные для вас, выходящие за рамки вопроса и вредные для меня, чтобы публиковать слишком много):

Этосоздает один список элементов правильно.Однако, если вы попытаетесь добавить снова, вы перемещаете головку к временному объекту, устанавливая заголовок в nullptr.Затем вы перебираете курсор по списку, уничтожая любые узлы, которые могли существовать, пока их больше нет.Тот факт, что вы только что присвоили nullptr курсору, не является проблемой, поскольку вы сразу же отбрасываете любое значение, которое оно могло иметь, создавая новый список с одним элементом, удерживаемым курсором вместо заголовка.Затем вы выходите из области видимости, уничтожая курсор, и, следовательно, также уничтожая новый элемент, который вы только что добавили в курсор.

Но самая большая проблема - ваша функция трассировки, которую вы используете, чтобы понять свой список, но она не делает ничего удаленно, как вы хотите.Это самая большая проблема, потому что вы думаете, что понимаете, что происходит на основе плохой информации.Если трассировка лежит на вас, то вы нигде не сможете использовать ее для понимания add.

Вот функция трассировки, которая будет правильно печатать текущее содержимое вашего списка, не разрушая его:

void trace() {
    cout << "trace: ";
    shared_ptr<node> cursor = head; // SHARE, do not lose head, read the docs
    while (cursor.get()) {
        cout << cursor->data << ", ";
        cursor = cursor->next;
    }
    cout << endl;
}

Я бы предложил вызывать функцию трассировки дважды подряд.Если он не разрушает список при печати, тогда второй вызов должен иметь такой же вывод, как и первый.Чтобы исправить добавление, вам нужно упростить его.Просто следуйте указаниям обычного узла.Ваша большая проблема заключалась в том, чтобы использовать «swap», чтобы поместить ваши фактические данные под единоличный контроль над временным объектом, что быстро ДЕЛАЕТ ЕГО ЗАДАНИЕ, которое уничтожает все ваши данные.

...