简体   繁体   中英

C++ return a const pointer inside a none const pointer function

I have coded this function to find the shallowest leaf in binary search tree it is not the best but it does the job, the leaf have to be returned after it have been found.

it is a necessary condition not to change the function prototype.

my problem is pointed by a comment below

The problem is i am returning a const Pointer inside a none const pointer function, i look before posting the question, all of the question where functions inside of classes, I have not studied them so I don't know if it is the same for functions outside of classes, is there any workaround for the problem ?

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;
}

Without changing the function's signature the only way to solve this problem is with const_cast :

return const_cast<Node*>(root);

Since your code looks like C rather than C++ to me, a C-style cast may be more appropriate:

return (struct Node*)root;

In any case changing the function signature is a way cleaner approach. If you make your function a template, it will work with both const and non-const nodes:

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

Two ways can be used. The first will help maintain a good project and the second will propagate undefined behaviours , giving an unstable software that behaves differently in the same situatuion.

The first way is to return a copy of the const Node, thus allowing the API user of min_depth_leaf to modify the returned copy value, without modifying the original value in the tree, code will be like:

#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;
}

The other way (to be avoided) is to cast the const value to non const, causing undefined behaviors (UB), for example:

  • If the API user deletes the returned Node from min_depth_leaf that is returned it will be deleted from the tree.

  • if the API user creates the tree on stack in a function f1() and then gets the result of the min_depth_leaf in another function f2(), he will be surprised that as soon as f2() ends, the returned node will be deleted from stack, even though f1() is still not ended, so f1() will get garbage when accessing it .

This way is by using const_cast

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM