使用修改后的指向常量的指针返回指向非常量的指针
Return pointer-to-non-const using modified pointer-to-const
从函数返回指向非const
的指针的最佳做法是什么,其中该指针是通过将(非const
)指针修改为-const
来获得的?像这样:
NODE *top_level(const NODE *input)
{
while (input->parent != nullptr)
input = input->parent; // NODE::parent is (non-const) NODE*
return input; // Compile failure:
// Cannot convert from 'const NODE *' to 'NODE *'
}
我可以在返回时离开const_cast
和const
,这似乎很好,但有更好的方法吗?
至少在标准库中,最佳实践是提供const
和非const
重载。例如std::strchr
在<cstring>
中声明为
char *strchr(char *s, int c);
char const *strchr(char const *s, int c);
类似地,像std::map<T>::find
这样的功能也有这样的过载
iterator find(const Key& key);
const_iterator find(const Key& key) const;
请注意,第一个版本中没有const
限定符,尽管find
本身没有理由修改map
。(*)关键是你从find
中得到了一些可以用来修改映射的东西,所以通过一种"可变性的传递性",find
不可能是const
。我认为同样的情况也适用于你的问题。
或者,你可以使用const_cast
,但对我来说,这就像违背了承诺。
这种情况的有趣之处在于,如果你能保证你的函数永远不会在树的顶部项上调用(或者不管输入是什么),那么就不需要强制转换或重载:
struct node {
node *parent;
};
node *top(node const *n)
{
node *p = n->parent;
while (p->parent != 0)
p = p->parent;
return p;
}
编译时没有任何警告。
(*)如果std::map
被实现为一个展开树,find
将不得不对其进行修改,但我认为由于复杂性保证,该标准不允许使用展开树。
[编辑:经过两次编辑,我认为我的答案和larsmans的答案现在是一样的,但事情的顺序不同,不同选项的详细程度也不同。我鼓励人们不要对这个答案投赞成票,除非你看到它和larsmans'之间有一些重要的区别。如果没有人找到,我会删除它。]
如果您确信*input
的const
-ness应该而不是意味着该函数不会为您提供修改列表中其他节点的方法,那么修复方法是:
NODE *top_level(const NODE *input_)
{
NODE *input = const_cast<NODE*>(input_);
while (input->parent != nullptr)
input = input->parent;
return input;
}
但这对我来说似乎是错误的,,因为函数可以返回与中传递的指针值完全相同的指针值。
因此,由于它可以为其他代码(尽管是调用者)提供修改其输入的方法,因此其输入不应标记为const
。"正确"的解决方案是提供常量和非常量重载,因为这就是避免编写"偷偷带走常量"的函数的方法,比如strstr
的非重载C版本和其他返回非常量的字符串搜索函数。
如果不是因为从指向同一节点的指针中删除const的风险(假设输入在某种程度上被保证不是顶级节点,并且假设你仍然确信第一个节点的const不应该意味着列表中其他节点的const),那么你可以这样写:
NODE *top_level(const NODE *input)
{
NODE *result = input->parent;
while (result->parent != nullptr)
result = result->parent;
return result;
}
请注意,我们不再需要const_cast
,当我们添加了使函数本身成为负责任的const安全公民所必需的假设时,它已经消失了。系统正常工作!;-)
通常的解决方案,至少在接口级别,是在const
上重载,提供两个函数,NODE const* top_level( NODE const* input )
和NODE* top_level( NODE* input )
。如果您不想重复代码,那么可以使用const_cast
来实现其中一个。
- 将常量指针引用绑定到非常量指针
- 如何使用数据对象上的常量指针初始化类
- C++中的指针和常量问题不大
- 为什么我收到"从常量指针到指针的转换无效?
- 当成员值从指针更改为非指针时,C++常量问题
- 使用双指针传递 2D 常量数组
- C++/QT:使用指向私有成员的常量指针作为只读数据共享
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 模板推导:为什么函数指针模板定义在常量和/或引用时不匹配?
- 初始化指针的常量向量
- 区分接受常量参数的函数引用/指针和与函数参数同名的非常量参数
- 什么是常量指针常量引用类型的参数?(const X* const & p)
- 无法将"常量指针常量"传递给常量引用
- C++:如何创建一个临时对象,包含一个指针 - 常量或非常量,具体取决于上下文
- 具有函数指针常量数组的 C++ 模板化静态类
- 这个constexpr整数不是空指针常量吗
- 使指针常量C++
- C++11在stl容器中共享指针常量
- 空指针常量转换为右值
- 在参考 (T&) 和常量指针 (T* 常量) 之间进行选择