Как правильно обрабатывать переменную того же типа, что и класс, к которому она принадлежит?

#c

#c #c

Вопрос:

Я использую два приведенных ниже файла для своего проекта. Переменная, на которую я ссылаюсь, Node parent , изначально не была указателем, но я быстро обнаружил, что это не работает по очевидным причинам (память).

Поэтому я превратил его в указатель. Проблема в том, что parent , похоже, она неправильно обрабатывается в моем коде, поэтому в конечном итоге мое приложение выходит из строя при выполнении функции, подобной getParent() . Какие изменения могли бы устранить эту проблему?

Node.h

 #include <string>
#include <vector>
#include <iostream>
#include "Action.h"
class Node
{
  

Node.cpp

 #include "stdafx.h"
  

Комментарии:

1. Для повышения производительности вам следует перейти std::string title на const std::stringamp; title

2. Вам нужно научиться передавать параметры по ссылке.

3. Еще лучшая производительность : title(std::move(title)) 🙂 @EdHeal Я не думаю, что это дает преимущество в производительности, компилятор не может перемещать оптимизацию и вместо этого должен делать копию.

4. std::vector<Node> getChildren(); — Вы будете обожжены этим, если ваша цель — вернуть настоящих детей, а не их копии. Верните ссылку, если вы хотите, чтобы были возвращены фактические дочерние элементы.

5. Этот код изобилует потенциальным неопределенным поведением . Пример: и Node(std::string title, Node parent) конструктор, и Node::setParent(Node parent) установщик сохраняют адрес автоматической временной переменной (предоставленный параметр) в качестве значения this->parent элемента. В обоих случаях в момент завершения текущей функции этот объект перестает существовать, а указатель остается висячим. Я думаю, вам нужно больше изучить время жизни объекта, указатели, ссылки и т. Д., Прежде чем браться за это. Это не так тривиально, как вы, возможно, думаете. Скорее наоборот; это утомительная работа.

Ответ №1:

Вы должны проверить, является ли parent это nullptr или нет:

 bool Node::getParent( Nodeamp; node )
{
    if ( parent )
    {
        node = *parent;
        return true;
    }
    else
    {
        return false;
    }
}
  

Обратите внимание, что вам необходимо реализовать надлежащий конструктор копирования Node is.
Возможным решением является возврат указателя или ссылки на родительский узел, но в нескольких реализациях это опасно, потому что вы разрешаете доступ непосредственно к внутреннему члену. Решите, что хорошо для вас.

Просто предложение: если вы используете std::sharer_ptr или std::unique_ptr , некоторая реализация будет намного проще.

Комментарии:

1. Есть идеи, почему родительский элемент не присваивается должным образом? Я добавил конструктор копирования, который переносит все свойства. По сути, это узел с пустой строкой, без дочерних элементов, родительских элементов, действий и т. Д.

2. В методе getParent(…)? Вы уверены, что parent член не является nullptr ? Может быть, какой-нибудь фрагмент кода был бы полезен.

3. Я думаю, что это связано с SetParent(..), а не с getParent(..), Но не уверен, что может быть причиной этого.

4. void returntoPreviousNode() { Node *parent = currentNode.getParent(); if (parent == nullptr) { ; //Do nothing then. } else { currentNode = *currentNode.getParent(); } }

5. Например, это правильно выполнит currentNode = *currentNode.getParent(); но он всегда будет возвращать узел с пустым заголовком среди других пустых свойств

Ответ №2:

Вы должны проверить, имеет ли parent значение null или нет, прежде чем выполнять дефреференции.

преобразуйте подпись вашего getParent в:

 Node* Node::getParent()

Node* Node::getParent() {
    return parent;
}
  

И в вашем приложении всякий раз, когда вы обращаетесь к ней, сначала проверьте.

 Node * parent = getParent();
if(parent==nullptr){
    cout << "parent is nulln";
    raise error;
}else{
    // do whatever you want
}