对于我当前的编程分配,我必须构造一个二叉搜索树,并使用它按字母顺序从文件中插入单词,以制作一致性列表。程序完整,输出正确;该程序的主要部分完美。但是当程序完成并且调用析构函数时,它会与error in ./concordancebst : free(): invalid pointer
崩溃。我不知道问题是什么,我的析构函数看起来会起作用并在线查看代码似乎它应该也能正常工作。我可以通过使用std::unique_ptr
来解决这个问题,但从程序的范围来看似乎有点矫枉过正(在某种意义上我们还没有涵盖智能指针,我们在涉及动态内存的类已通过手动分配/解除分配处理。
BST.h
#ifndef BST_H
#define BST_H
#include <string>
class BST {
public:
BST() { root = nullptr; }
~BST();
void insert(const std::string word);
int getCount(const std::string word);
int length();
friend std::ostream& operator << (std::ostream &out_s, BST b);
private:
struct Node {
std::string word;
int count;
Node *left;
Node *right;
Node() { word = ""; count = 0; left = nullptr; right = nullptr;}
~Node();
};
Node *root;
void RInsert(Node* &t, std::string word);
int countNodes(Node *p);
void print(Node *p, std::ostream &out_s);
};
#endif
BST.cpp
#include "BST.h"
#include <string>
#include <iostream>
#include <iomanip>
BST::Node::~Node() {
delete left;
delete right;
}
BST::~BST() {
delete root;
}
int BST::countNodes(Node *p) {
if(p == nullptr)
return 0;
else
return countNodes(p->left) + countNodes(p->right) + 1;
}
int BST::getCount(const std::string word) {
Node *p = root;
while(true) {
if(p == nullptr)
return 0;
else if(word.compare(p->word) < 0)
p = p->left;
else if(word.compare(p->word) == 0)
return p->count;
else
p = p->right;
}
}
int BST::length() {
return countNodes(root);
}
void BST::RInsert(Node* &t, std::string word) {
if(t == nullptr) {
t = new Node;
t->word = word;
t->left = nullptr;
t->right = nullptr;
t->count++;
}
else if(word.compare(t->word) == 0)
t->count++;
else if(word.compare(t->word) < 0)
RInsert(t->left, word);
else //word.compare(t->word > 0)
RInsert(t->right, word);
}
void BST::insert(const std::string word) {
RInsert(root, word);
}
void BST::print(Node *p, std::ostream &out_s) {
if(p != nullptr) {
print(p->left, out_s);
out_s << std::setw(13) << p->word << std::setw(10) << p->count << std::endl;
print(p->right, out_s);
}
}
std::ostream &operator << (std::ostream &out_s, BST b) {
out_s << std::setw(13) << "Word" << std::setw(10) << "Count" << std::endl;
out_s << "---------------------------------------------" << std::endl;
b.print(b.root, out_s);
out_s << "---------------------------------------------" << std::endl;
out_s << "The file contains " << b.length() << " distinct words." << std::endl;
return out_s;
}
答案 0 :(得分:2)
std::ostream &operator << (std::ostream &out_s, BST b)
Pass by value^. b is copied.
由于BST
没有复制构造函数,因此调用默认复制构造函数并且不执行深层复制。 b
包含源BST
指针的副本,当从函数返回时销毁b
时,它会将所有源Node
与它一起带到严重。
修复有两个方面:
最直接,通过引用传递。
std::ostream &operator << (std::ostream &out_s, BST & b)
此代码间接违反了Rule of Three。 BST
和BST::Node
需要安全使用复制构造函数和赋值运算符。
最小的测试用例如下:
#include <iostream>
#include "BST.h"
int main()
{
BST t;
t.insert("A");
std::cout << t << std::endl;
return 0;
}