const输入与非const输出

const input vs non-const output

本文关键字:const 输出 输入      更新时间:2023-10-16

我的函数可以遍历对象树,并且不会修改树中的任何对象。

该功能看起来像这样:

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();