【问题标题】:C++ Moving By Reference, values doesn't change?C++ 通过引用移动,值不会改变?
【发布时间】:2021-03-05 13:22:09
【问题描述】:

我在tree 类中编写了以下方法:

public:
    node<T> *root;

template<class T>
node<T> *tree<T>::insert(node<T> *p, const T &key) {
    if (p == nullptr) {
       p = new node<T>(key);
    }
    //Some code
}

但我注意到即使执行 if 条件,树根的值也没有改变,是什么导致了这种行为?

这就是我在main.cpp 中的调用方式:

tree<int> t1{};
t1.insert(t1.root,7);

很明显,我是按引用而不是按值移动,因为我给了插入一个指向根节点的指针。 (root是指向根的指针)

我希望有人能清楚地解释我做错了什么以及如何解决这个问题,因为我在这个问题上停留了一天。

【问题讨论】:

  • 参数p传值​​;实际上,它是t1.root 的副本。调用者看不到函数中此参数的更改。
  • @IgorTandetnik 为什么它是一个指针
  • @user128250 指针也是值。对于说它们不作为值传递的指针没有特殊的规则(这是一个非常常见的误解)。
  • 即使指针是按值复制的,它仍然具有相同的内部值(指向同一个对象)
  • @user128250 其实很简单,只是新手有把事情复杂化的习惯。我相信你会同意你有两个变量proot,你用p = ... 改变其中一个。为什么要改变另一个变量?如果它们都是整数,它会改变另一个变量吗?为什么指针应该有所不同?事实上,指针并没有什么不同。

标签: c++ class pointers reference


【解决方案1】:

您通过值传递t1.root,而不是通过引用或指针。因此,函数insert 获得了自己的变量t1.root 的副本,更改此副本不会更改原始变量。

要解决这个问题,你可以通过引用或指针传递,而不是按值传递。

为了通过指针传递,您可以将函数insert更改为以下内容:

node<T> *tree<T>::insert(node<T> **pp, const T &key) {
    if (*pp == nullptr) {
       *pp = new node<T>(key);
    }
    //Some code
}

函数的第一个参数现在是指向指针的指针,即双指针。为了从双指针中获取指针,您必须使用* 取消引用一次。

调用函数时,还必须在t1.root中添加一个&amp;(操作符地址),像这样:

t1.insert(&t1.root,7);

这样,您将传递t1.root的地址,以便函数可以修改原始值。

或者,您可以通过引用传递t1.root,如下所示:

node<T> *tree<T>::insert(node<T> *&p, const T &key) {
    if (p == nullptr) {
       p = new node<T>(key);
    }
    //Some code
}

在这种情况下,你不必在调用函数时在t1.root前面添加&amp;,也不必在函数体中使用*进行解引用。它实际上与使用双指针相同,但 C++ 会为您处理取消引用和传递地址,因此您不必担心。

【讨论】:

    【解决方案2】:

    因为p 不是root。使用 root 作为参数调用insert 函数复制 指向p 的指针,它不会使p 成为与root 相同的变量。所以对p 的更改对root 没有影响。

    如果你想让 proot 是同一个变量,那么你必须使用一个引用

    template<class T>
    node<T> *tree<T>::insert(node<T> *&p, const T &key) {
    

    现在指针 p 是对用于调用 insert 的任何指针的引用,因此对 p 的更改将更改原始指针(在您的情况下为 root)。

    【讨论】:

    • 但是我不明白为什么,我发了一个指向root的指针保存到p中,这有什么问题?
    • 另外,如果我们假设 p 是按值复制的,它是一个指针,这并不重要,因为它仍然会在访问时指向同一个东西
    • @user128250 但是(这是关键的事情)你并没有改变它所指向的东西,你正在改变指针本身。
    • 你不发送指向根的指针。 root 本身是指向某些 Node&lt;T&gt; 的指针。你永远不会传递指向root 的指针。您也永远不会更改 p 所指向的内容,您只需更改 p 所指向的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 2017-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多