const输入与非const输出
const input vs non-const output
我的函数可以遍历对象树,并且不会修改树中的任何对象。
该功能看起来像这样:
static Node* findMatchingNode(const Node& root, const SomeFilterData& d);
struct Node {
Node* left;
Node* right;
};
该功能可以返回树中的根或任何对象,也可以返回任何对象。比给定的声明很明显,我必须在某个地方执行 const_cast ,这在大多数情况下都是禁止的。
函数保证constness并同时允许任何人修改其输出?
是可以接受的吗?编辑。我尚未清楚地说明,我的功能确实没有修改树上的任何节点,也不会创建新节点,而是纯函数。我想在那里总是有const
预选赛,以清楚地告诉所有人该功能不会修改任何内容
编辑。背后的不言而喻的问题是,在函数执行期间(仅在功能内部)中没有法定方法来表达输入的构造,而无需执行输出constness。
一如既往,您无法修改const
数据,因为它是恒定的。特别是:
即使const_cast可能会使用结果指针或参考来删除constness或挥发性,但使用结果指针或参考来写入被声明为const的对象或访问被声明为挥发性的对象的对象。
(从这里)
因此,如果指向const
输入参数root是一个明智的结果,则返回类型也应为const
。无论如何,您应该是真的要小心返回指针:到目前为止,您的功能可以将指针返回到临时的指针!
更好地返回boost::optional<Node>
或std::optional<Node>
(如果后者将其纳入C 17,并且您使用该标准)。
如果您的功能仅对可修改的输入root
有意义(例如,如果结果必须修改和,则结果可以是root
的地址),请丢弃const
在您的声明中。这也将阻止输入root
暂时。
很可能是您潜在XY问题的最清洁修复:
如果它适合您的用例(我发现它不太可能高度),那么最有可能更好的选项是在迭代的数据结构上定义您的算法,例如树或一棵树或列表(无论您的Node
是一个节点),然后将迭代器返回到匹配的节点,或者是过去的迭代器(相对于高级结构),如果不存在这样的节点。
至于 const
-vs.-non- const
讨论:使用迭代器选项,您可以在高级别结构的constness和您与参考节点的参考节点和您比较的参考节点之间进行区分,从而通过将非const
迭代器与高级别结构相提并论。和参考输入节点的const &
参数(现在暂时不是问题)。
从我的问题中可以看到,您的功能甚至可以用std::find_if
替换。然后,您首先不会有这个问题。
您的代码不正确,它会删除const。这就是为什么您遇到"必需" const的问题。不要那样做:
static const Node* findMatchingNode(const Node& root, const SomeFilterData& d);
您可能会指出,您可能需要从 dis 修改节点的另一个函数调用此函数,因此需要一个非const结果。因此,应该是一个具有完全不同签名的新功能:
static Node* findMatchingNode(Node& root, const SomeFilterData& d);
您可能会指出它们具有相同的身体,并且有干燥原理(干=不要重复自己=没有拷贝性的代码)。是的,所以请在此处进行快捷方式:const_cast。我认为在这种情况下是可以的,因为它是唯一的目的是共享代码,而且很明显,它没有违反任何const-correctness原则。
//This function does not modify anything
static Node* findMatchingNode(Node& root, const SomeFilterData& d) {
return const_cast<Node*>(findMatchingNode(const_cast<const Node&>(root),d));
}
loki asari建议添加两个版本findMatchingNode()
调用的第三个私有功能findMatchingNodeCommon()
。然后,您可以减少一个const_cast
。如果您想进行极端,则可以使findMatchingNodeCommon()
模板进行模板,然后所有const_cast
S离开。我认为这不值得打扰,但它们是非常有效的意见,因此值得一提。>
逐返回与const成员函数之间有什么关系?
如果您想通过检查器方法的引用返回此对象的成员,则应使用Reference to-Const(const X&amp; Inspect()const)或值(x Inspect()const)将其返回。。
是的,您应该按值或const参考/指针返回。您不使用this
,但模式相同。
我会看一下STL如何做到。在那里,您有一个序列(由迭代器界定),一个定义匹配和模板函数的谓词。由于它是模板函数,因此它会自动将返回值const-Qualifier匹配到参数的函数。
。如果出于某种原因,您不想编写模板功能,也可以添加两个过载,因为您可以使用不同的const-qualifiers edromload函数。
我想回答自己,因为原来的问题没有正确地塑造。因此,我的答案不能被视为适当的。
没有任何合法的方式来表达输入的构成(在函数执行期间),而无需强迫用户不修改输出(也不强制执行输出constness)。
没有_const_cast _:
的方式static Node* findMatchingNode(Node& root, const SomeFilterData& d);
看起来并不能保证输入树构成。
原始函数声明允许这样的黑客,这也是不合适的:
const Node& root = ...
Node* result = findMatchingNode(root, filter);
result->doBadNonConstThings();