C ++在一个无常量指针函数内返回一个const指针

时间:2017-06-10 03:52:46

标签: c++ pointers binary-search-tree

我已经对这个函数进行了编码,以便在二叉搜索树中找到最浅的叶子,但这不是最好的,但它完成了工作,叶片必须在找到后返回。

这是不更改功能原型的必要条件。

我的问题由下面的评论指出

问题是我在一个无常量指针函数中返回一个const指针,我在发布问题之前看,所有问题在哪些函数里面的类,我还没有研究它们所以我不知道它是不是对于类之外的函数,相同的问题是否有解决方法?

struct Node {
    int _data;
    struct Node *_left;
    struct Node *_right;
};
//-----------------------------------------------------------------------------------
struct Node *min_depth_leaf(const struct Node *root, int &depth) {
    int left_depth;
    int right_depth;
    if (root == NULL) {
        depth = INT32_MAX;
        return NULL;
    } else if (root->_left == NULL && root->_right == NULL) {
        depth = 0;
        return root;//<-------------- The problem lays here
    } else if (root->_left != NULL || root->_right != NULL) {
        struct Node *left_node = min_depth_leaf(root->_left, left_depth);
        struct Node *right_node = min_depth_leaf(root->_right, right_depth);
        if (right_depth < left_depth) {
            right_depth += 1;
            depth = right_depth;
            return right_node;
        } else {
            left_depth += 1;
            depth = left_depth;
            return left_node;
        }
    }
    return NULL;
}

2 个答案:

答案 0 :(得分:1)

在不更改功能签名的情况下,解决此问题的唯一方法是使用const_cast

return const_cast<Node*>(root);

由于您的代码对我来说似乎是C而不是C++,因此C风格的演员可能更合适:

return (struct Node*)root;

在任何情况下,更改功能签名都是一种更清洁的方法。如果您将函数设置为模板,它将适用于const和非const节点:

template<typename T> T* min_depth_leaf(T* root, int &depth)

答案 1 :(得分:1)

可以使用两种方法。第一个将帮助维护一个好的项目,第二个将传播未定义的行为,给出一个不稳定的软件,在相同的情况下表现不同。

第一种方式是返回const节点的副本,从而允许min_depth_leaf的API用户修改返回的拷贝值,而无需修改树中的原始值,代码就像:

#include<cstdlib>
struct Node {
    int _data;
    struct Node *_left;
    struct Node *_right;
};
//-----------------------------------------------------------------------------------
struct Node *min_depth_leaf(const struct Node *root, int &depth) {
    int left_depth;
    int right_depth;
    if (root == NULL) {
        depth = INT32_MAX;
        return NULL;
    } else if (root->_left == NULL && root->_right == NULL) {
        depth = 0;
        // return a copy
        Node * p = new Node();
        p->_data=root->_data;
        p->_left = root->_left;
        p->_right = root->_right;
        return p;
    } else if (root->_left != NULL || root->_right != NULL) {
        struct Node *left_node = min_depth_leaf(root->_left, left_depth);
        struct Node *right_node = min_depth_leaf(root->_right, right_depth);
        if (right_depth < left_depth) {
            right_depth += 1;
            depth = right_depth;
            return right_node;
        } else {
            left_depth += 1;
            depth = left_depth;
            return left_node;
        }
    }
    return NULL;
}

另一种方式(要避免)是将const值强制转换为非const,导致未定义的行为(UB),例如:

  • 如果API用户从返回的min_depth_leaf中删除了返回的节点,它将从树中删除。

  • 如果API用户在函数f1()中在堆栈上创建树,然后在另一个函数f2()中获取min_depth_leaf的结果,那么只要f2()结束,他就会感到惊讶返回的节点将从堆栈中删除,即使f1()仍未结束,因此f1()在访问时会变得无用。

这种方式是使用const_cast

 return const_cast<Node *>(root); //never use this