C ++: член указателя закрытого класса возвращает неопределенные значения - PullRequest
0 голосов
/ 20 сентября 2019

Я пытаюсь напечатать порядок уровней красно-черного дерева, однако указатели на другие узлы всегда возвращают любые числа после вставки в очередь STL.Что я здесь не так делаю?

Вот реализация моего класса узлов:

// rbtree-node.h
class RBTreeNode
{
public:
  // RBTreeNode(int value, Color color) : value_(value), color_(color), left_(nullptr), right_(nullptr), parent_(nullptr) {}
  RBTreeNode(int value, Color color) : value_(value), color_(color) {}
  ~RBTreeNode()
  {
    delete left_;
    delete right_;
    delete parent_;
  }

  void setLeft(RBTreeNode *node);
  RBTreeNode *getLeft();

  void setRight(RBTreeNode *node);
  RBTreeNode *getRight();

  void setParent(RBTreeNode *node);
  RBTreeNode *getParent();

  void setValue(int value);
  int getValue();

  void setColor(Color color);
  Color getColor();

  bool hasRedChild();
  bool isParentLeftChild();

  void print();

private:
  int value_;
  RBTreeNode *left_ = nullptr;
  RBTreeNode *right_ = nullptr;
  RBTreeNode *parent_ = nullptr;
  Color color_;
};
// rbtree-node.cpp
void RBTreeNode::setLeft(RBTreeNode *node)
{
  this->left_ = node;
}

RBTreeNode *RBTreeNode::getLeft()
{
  return this->left_;
}

void RBTreeNode::setRight(RBTreeNode *node)
{
  this->right_ = node;
}

RBTreeNode *RBTreeNode::getRight()
{
  return this->right_;
}

void RBTreeNode::setParent(RBTreeNode *node)
{
  this->parent_ = node;
}

RBTreeNode *RBTreeNode::getParent()
{
  return this->parent_;
}

void RBTreeNode::setValue(int value)
{
  this->value_ = value;
}

int RBTreeNode::getValue()
{
  return this->value_;
}

void RBTreeNode::setColor(Color color)
{
  this->color_ = color;
}

Color RBTreeNode::getColor()
{
  return this->color_;
}

bool RBTreeNode::isParentLeftChild()
{
  return this->parent_ != NULL && this->parent_->left_ == this;


void RBTreeNode::print()
{
  std::cout << "Value: " << this->value_ << ", Color: " << this->color_ << ", Left: " << this->left_ << ", Right: " << this->right_ << std::endl;
}

Затем я вставляю один узел:

    // ...
    RBTreeNode node = RBTreeNode(n, BLACK);
    root_ = &node;
    return root_;
    // ...

ПотомЯ пытаюсь напечатать это здесь:

void RedBlackTree::printLevelOrder()
{
  // Use BFS in order to print the tree
  std::queue<RBTreeNode *> queue;
  queue.push(root_);

  while (!queue.empty())
  {
    RBTreeNode *current = queue.front();
    std::cout << "Queue: ";
    std::cout << "Value: " << current->getValue() << "(L: " << current->getLeft() << ", R: " << current->getRight() << ") "
              << std::endl;

    if (current->getLeft() != NULL)
    {
      queue.push(current->getLeft());
    }

    if (current->getRight() != NULL)
    {
      queue.push(current->getRight());
    }
    queue.pop();
  }
  std::cout << std::endl;
}

При запуске я всегда получаю ошибку сегментации, потому что левый и правый узлы-члены всегда возвращают случайные значения.

Спасибо уже заранееза помощь!

1 Ответ

0 голосов
/ 20 сентября 2019

Одна из проблем заключается в том, что вы храните указатели на локальные переменные в очереди:

RBTreeNode node = RBTreeNode(n, BLACK);   // locally created value
root_ = &node;   // pointer to local
return root_;    // returning pointer to local.  If used outside the function, undefined behavior

По сути, вы должны разработать свой код, чтобы он содержал указатели на объекты, которые все еще будут активны при доступе к объекту черезэтот указатель.

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

RBTreeNode* node = new RBTreeNode(n, BLACK);
root_ = node; 
return root_; 

Конечно, теперь вам нужно правильно управлять памятью (правильная очистка / освобождение с использованием delete и т. Д.).

Другой альтернативой является использование интеллектуальных указателей, таких как std::unique_ptr, которые обрабатывают очистку после того, как указатель выйдет из области видимости.

...