2017-06-10 108 views
0

我已经编写了这个函数来查找二叉搜索树中最浅的叶子,它不是最好的,但它做的工作,叶子必须在找到它之后返回。C++在非常量指针函数中返回一个常量指针

它是不改变函数原型的必要条件。

我的问题是由以下

问题是我是回一个没有const的指针函数内部一个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; 
} 
+0

感谢您接受我的答案。 –

回答

1

可以使用两种方法。第一个将有助于保持一个好项目,第二个将传播未定义的行为,给出一个不稳定的软件,在同样的情况下行为不同。

第一种方式是返回常量节点的一个副本,从而使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的,导致未定义的行为(UB),例如:

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

  • 如果API用户在函数f1()中的堆栈中创建了树,然后在另一个函数f2()中获取了min_depth_leaf的结果,他会惊讶的发现,只要f2()结束,即使f1()仍然没有结束,节点也会从堆栈中删除,所以f1()在访问它的时候会得到垃圾。

这种方法是使用的const_cast

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

在不改变函数的签名来解决这个问题的唯一方法是使用const_cast

return const_cast<Node*>(root); 

因为你的代码看起来像C而非C++对我来说,一个C样式转换可能会更适当的:

return (struct Node*)root; 

在任何情况下更改函数签名是一种更清洁的方法。如果你将你的函数作为模板,它可以同时用于const和non-const节点:

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