【问题标题】:How to dereference a pointer passed by reference in c++?如何取消引用在c ++中通过引用传递的指针?
【发布时间】:2010-12-04 19:32:49
【问题描述】:

我正在做(类似的事情):

void insert(Node*& node, string val, Node* parent)
{
   if (node == NULL)
     instantiateNode(node, val, parent);
   else
     insert(node->child, val, node);
}

问题是,instantiateNode(..., parent) 似乎修改了在设置*parent 时传递给函数的原始*&nodeinstantiateNode()应该改变node,但如果它改变parent,那么你有一个节点被设置为它的父节点,这没有意义,也没有不工作。完全没有。

我完全关心指针引用的原因是因为它消除了特殊情况并显着减少了我必须做的错误检查量。由于我这样做是为了减少行数和琐碎的算法重复,因此我可以通过将代码行数增加大约一倍来解决这个问题。但我宁愿不这样做,而且我觉得 应该 有一种方法可以取消引用指针引用以获取指向同一对象的新指针。而且,真的,我认为 *&node*parent 的传递应该可以做到,但显然 gcc 正在优化它。

【问题讨论】:

  • 您能否发布您的完整代码以及您想要实现的目标是什么?这看起来是一个相当简单的插入,为什么还要处理指针引用?
  • 您的问题听起来不清楚。为什么不发布实例化节点?它应该修改节点指针(并且整个事情也应该能够修改父节点)对我来说似乎是可以预期的。
  • 目前尚不清楚(至少对我而言)您正在寻找的代码 sn-p 的行为变化是什么。我假设将node 作为参考传递的全部意义在于它可以从函数内部进行修改。此外,函数名称instantiateNode 似乎暗示它将创建一个新节点,可能是通过修改它的参数。关于复制指针,你的意思是Node *copy = node;
  • "显然 gcc 正在优化它" -> 不,不是。不要责怪编译器/优化器。它几乎从不出错,而且 GCC 出错的频率甚至比大多数都少。您的代码正在执行您告诉它的操作,这可能是也可能不是您想要的。
  • 我应该在我之前的评论中添加不允许优化器更改程序的行为方式。只有在最奇怪的情况下(未定义的行为、优化器错误以及规范中的一些事情,如赋值/复制构造函数省略)才会这样做。

标签: c++ reference pointers dereference


【解决方案1】:

应该有一种方法可以取消引用指针引用以获取指向同一对象的新指针。

那么,这个怎么样?

Node* n = node;

现在你有一个非引用指针,它指向与节点相同的对象,正是你所要求的。

我 95% 确定您面临的问题与引用无关,而是与 instantiateNode 中的错误逻辑或您对它的使用有关。这就是为什么如果您向我们提供有关代码应该做什么的更多信息,或者甚至将代码发布到实例化节点,将会很有用。

【讨论】:

  • 你说得对。我想我让自己陷入了细节之中,但我很早就尝试过,而 gdb 表明它仍然指向错误的东西。但是即使做Node* n = &(*node); 也不能解决它,所以要么我不走运,要么更可能的是,我在做一些愚蠢的事情。不过,这是一个小功能,而且我已经写了很多与它非常相似的东西,而且我已经重写了我什至不知道多少次等等,所以我仍然不确定发生了什么.如果我弄明白了,我会回来的。
【解决方案2】:

node 是对指针的引用,这意味着如果函数设置 node,则传入的值会改变。这就是引用的工作原理。

如果您不希望节点在调用函数中发生变化,请不要将其作为引用。

还是我误会了什么?

【讨论】:

  • 不,你是对的:我想改变节点。但后来我认为,当我将它作为parent (这不是参考)传递给insert() 时,它应该被复制,parent 应该是一个新指针,指向与node 在上一个函数。
  • 但是您没有将parent 传递给insert()
  • node 变成了parent,因为insert() 对节点的子节点进行操作。签名:insert(node, item, parent)。来电:insert(node->child, item, node)
  • 对不起,我不知何故错过了您递归调用insert。是的,第二次调用 insert 时,该帧中的parent 变量应该与调用者帧中的node 变量相同。你可以改变parent指向的东西(即Node结构的内容),但你不能改变parent本身。
【解决方案3】:

我认为node 不需要通过引用传递。一个简单的指针应该可以完成这项工作。这是因为您不需要直接更改它。你为什么要把它传递给instantiateNode()?它将始终为 NULL,那么它有什么用呢?如果instantiateNode() 的第一个参数也作为引用传递,为什么?你传入了父级,所以instantiateNode() 可以访问node 应该通过parent->child 代表的东西。即使出于某种原因instantiateNode() 确实通过引用将其作为参数并且必须这样做,我相信如果您从insert() 的第一个参数中删除引用,该函数仍然可以工作。无论instantiateNode() 对该值做什么,都会在函数返回时丢失。很抱歉,这太令人困惑了,但我想不出更好的表达方式。

您的问题有另一种解释...也许您对insert() 的调用应该是:

insert(node, val, node->child);

【讨论】:

  • 该代码似乎只是构建一个列表,它只是附加到 lasts 节点子节点,即 child==0 的位置。假设这就是它应该做的事情,我觉得这很好。
  • 我将它传入,如果它为NULL,我将它设置为一个新的孩子。所以我实际上是在影响指针本身。不过,通过进行大量的条件检查,可以通过小杂技来完成。我这样做的唯一原因是因为它是一棵 3-5 棵树,我不想在每个循环上检查 3-5 件事。
猜你喜欢
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 2020-03-14
  • 2012-03-03
  • 1970-01-01
  • 2014-07-27
相关资源
最近更新 更多