【发布时间】:2021-05-04 12:11:28
【问题描述】:
我有一个看起来像这样的模板类
namespace binary_search_tree {
template <typename T>
class binary_tree {
private:
T d;
binary_tree<T> *l, *r;
public:
binary_tree(T d) : d(d), l(nullptr), r(nullptr)
{}
void insert(T d) {
binary_tree<T>* branch = new binary_tree<T>(d);
if(d <= this->d) {
this->l = branch;
} else {
this->r = branch;
}
}
const T data() const {
return d;
}
const binary_tree<T>* left() const {
return l;
}
const binary_tree<T>* right() const {
return r;
}
};
}
我有一个 test.cpp 文件,用于测试我的课程
#include "binary_search_tree.h"
#include "test/catch.hpp"
#include <vector>
// test data version: 1.0.0
template<typename T>
using tree_ptr = typename std::unique_ptr<binary_search_tree::binary_tree<T>>;
template<typename T>
static void test_leaf(const tree_ptr<T> &tree,
const T& data, bool has_left, bool has_right)
{
REQUIRE(data == tree->data()); // ***************
REQUIRE((bool) tree->left() == has_left); // <---- *** problem ***
REQUIRE((bool) tree->right() == has_right); // ***************
}
template<typename T>
static tree_ptr<T> make_tree(const std::vector<T> &data)
{
if (data.empty())
return tree_ptr<T>(nullptr);
auto data_iter = data.begin();
auto tree = tree_ptr<T>(new binary_search_tree::binary_tree<T>(*data_iter));
++data_iter;
for (; data_iter != data.end(); ++data_iter)
{
tree->insert(*data_iter);
}
return tree;
}
TEST_CASE("data_is_retained")
{
auto tested = make_tree<uint32_t>({4});
test_leaf<uint32_t>(tested, 4, false, false);
}
TEST_CASE("smaller_number_at_left_node")
{
auto tested = make_tree<uint32_t>({4, 2});
test_leaf<uint32_t>(tested, 4, true, false);
test_leaf<uint32_t>(tested->left(), 2, false, false);
}
TEST_CASE() 函数来自一个为测试而设计的单独头文件。
问题源于在 test_leaf() 函数中调用 left() 和 right() 时。
编译器说
invalid initialization of reference of type ‘tree_ptr<unsigned int>&’ {aka ‘const
std::unique_ptr<binary_search_tree::binary_tree<unsigned int>,
std::default_delete<binary_search_tree::binary_tree<unsigned int> > >&’} from expression of
type ‘binary_search_tree::binary_tree<unsigned int>*’
我不确定如何使这些类型匹配。我尝试过以各种方式返回参考,但这似乎让事情变得更糟。我应该返回一个 unique_ptr 吗?我对 default_delete 是什么感到困惑。在我看来,我应该返回某种引用而不是指针。我不确定如何在课堂上安全地做到这一点。
【问题讨论】:
-
this->l = &branch;= 灾难的秘诀。分配一个非常临时的自动对象的地址。到什么应该是动态数据结构模型。this->r = &branch也是如此。在离开branch的周围范围的那一刻,该对象不再存在,留下一个悬空指针。 -
编译器错误还有吗?
-
注意:在传递 'void test_leaf(tree_ptr
&, const T&, bool, bool) 的参数 1 [with T = unsigned int; tree_ptr = std::unique_ptr<:binary_tree int>, std::default_delete<:binary_tree int> > >]' -
@WhozCraig 我应该完全避免使用指针吗?
-
显然,在您的最后一个测试中,您不能同时对 test_left 的调用进行编译,因为对 left 的调用返回一个指针,而在第一个类中,您传递了一个对象。