首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >引用的初始化无效

引用的初始化无效
EN

Stack Overflow用户
提问于 2021-01-31 06:17:44
回答 1查看 124关注 0票数 1

我有一个模板类,如下所示

代码语言:javascript
复制
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文件

代码语言:javascript
复制
#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()时,问题就出现了。

编译器说

代码语言:javascript
复制
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<>是什么感到困惑。在我看来,我应该返回某种类型的引用而不是指针。我不确定如何在我的课堂上安全地做到这一点。

EN

回答 1

Stack Overflow用户

发布于 2021-01-31 07:32:48

你的问题在这一行上:

代码语言:javascript
复制
test_leaf<uint32_t>(tested->left(), 2, false, false);

binary_tree<T>::left返回一个指向树的左子树的原始的、非所属指针,但是test_leaf需要一个对std::unique_ptr<binary_tree<T>>的引用。

这里的解决方案是将test_leaf更改为接受原始指针或引用:

代码语言:javascript
复制
template<typename T>
static void test_leaf(binary_search_tree::binary_tree<T>& tree,
                      const T& data, bool has_left, bool has_right)
{
    REQUIRE(data == tree.data());
    REQUIRE(static_cast<bool>(tree.left()) == has_left);
    REQUIRE(static_cast<bool>(tree.right()) == has_right);
}

(请注意,tree的类型确实应该是const合格的,但是您的binary_tree类模板没有足够的const-correct来支持现在的实际工作)

然后,将调用test_leaf的所有位置改为传递对底层对象的引用。例如:

代码语言:javascript
复制
test_leaf<uint32_t>(tested, 4, true, false);
test_leaf<uint32_t>(tested->left(), 2, false, false);

将更改为

代码语言:javascript
复制
test_leaf<uint32_t>(*tested, 4, true, false);
test_leaf<uint32_t>(*tested->left(), 2, false, false);

通常,不假定指向对象的任何所有权的函数应接受对智能指针所拥有的对象的引用或原始指针。传递对智能指针本身的引用不会增加任何安全性,并且不必要地将函数的使用限制为仅由特定类型的智能指针拥有的动态分配的对象。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65973702

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档