类型const节点的绑定参考*&到节点*const

发布于 2025-02-12 15:56:16 字数 3176 浏览 1 评论 0原文

我正在尝试实现一个通用树,并且在函数getsizerecursive 行1为什么不能使用const node*& root。同样,我在第2行中遇到了同样的错误。编译器给出了一个我无法理解的错误。

graph.cpp: In function 'int getSizeRecursive(const node*&)':
graph.cpp:56:40: error: binding reference of type 'const node*&' to 'node* const' discards qualifiers
   56 |         for(const node* &child : root->children) // line 2
      |                                        ^~~~~~~~
graph.cpp: In function 'int main()':
graph.cpp:69:36: error: binding reference of type 'const node*&' to 'node*' discards qualifiers
   69 |         cout << getSizeRecursive(t.root) << endl;
      |                                  ~~^~~~
graph.cpp:51:35: note:   initializing argument 1 of 'int getSizeRecursive(const node*&)'
   51 | int getSizeRecursive(const node* &root){ // line 1
      |                      ~~~~~~~~~~~~~^~~~
[Finished in 2.9s]
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
class node{
public:
    int data;
    vector<node*> children;

    node(int val){
        data = val; // this->data = data
    }
    ~node(){
        for(int i = 0 ;i<children.size();i++){
            if(!children[i])
                delete children[i];
        }
    }
};
class GenericTree{
public:
    node* root; // line 3
    int size;
    
    GenericTree(vector<int> nums){
        stack<node*> st;
        size = 0;
        for(int i = 0;i<nums.size();i++){
            node *n = new node(nums[i]);
            if(i == 0){
                root = n;
                st.push(n);
                ++size;
            }else{
                if(n->data == -1){
                    st.pop();
                }else{
                    // cout << "In me" << endl;
                    st.top()->children.push_back(n);
                    st.push(n);
                    ++size;
                }
            }
        }
    }
    // tells us the number of nodes
    int getSize(){
        return size;
    }
};
int getSizeRecursive(const node* &root){ // line 1
    if(root->children.size()==0)
        return 1;

    int size = 0;
    for(const node* &child : root->children) // line 2
        size  += getSizeRecursive(child);
    return size+1;
}
int main(){
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    vector<int> v{10,20,-1,30,50,-1,60,-1,-1,40,-1,-1};
    GenericTree t(v); // node that tree has been created 
    cout << t.size << endl;
    cout << getSizeRecursive(t.root) << endl;
    return 0;
}

我从中可以理解的是,编译器无法将引用到const Node const pointer to node ,但我的问题是为什么它会服用<代码> t.root 作为const指向节点的指针,而实际上只是指针到Node(请参阅第3行)。

我是C ++的新手。任何帮助将不胜感激。

编辑:我之所以使用const*&amp; root是因为我不想将root的副本传递给getsizerecursive,但是在此期间,由于我已通过参考,我已经使用了const,以便此参考仅读取根指针而不修改它。

I am trying to implement a generic tree and in the function getSizeRecursive line 1why cannot i use const node* &root. Similarly, i am getting the same mistake in line 2.The compiler is giving an error which i am not able to comprehend.

graph.cpp: In function 'int getSizeRecursive(const node*&)':
graph.cpp:56:40: error: binding reference of type 'const node*&' to 'node* const' discards qualifiers
   56 |         for(const node* &child : root->children) // line 2
      |                                        ^~~~~~~~
graph.cpp: In function 'int main()':
graph.cpp:69:36: error: binding reference of type 'const node*&' to 'node*' discards qualifiers
   69 |         cout << getSizeRecursive(t.root) << endl;
      |                                  ~~^~~~
graph.cpp:51:35: note:   initializing argument 1 of 'int getSizeRecursive(const node*&)'
   51 | int getSizeRecursive(const node* &root){ // line 1
      |                      ~~~~~~~~~~~~~^~~~
[Finished in 2.9s]
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
class node{
public:
    int data;
    vector<node*> children;

    node(int val){
        data = val; // this->data = data
    }
    ~node(){
        for(int i = 0 ;i<children.size();i++){
            if(!children[i])
                delete children[i];
        }
    }
};
class GenericTree{
public:
    node* root; // line 3
    int size;
    
    GenericTree(vector<int> nums){
        stack<node*> st;
        size = 0;
        for(int i = 0;i<nums.size();i++){
            node *n = new node(nums[i]);
            if(i == 0){
                root = n;
                st.push(n);
                ++size;
            }else{
                if(n->data == -1){
                    st.pop();
                }else{
                    // cout << "In me" << endl;
                    st.top()->children.push_back(n);
                    st.push(n);
                    ++size;
                }
            }
        }
    }
    // tells us the number of nodes
    int getSize(){
        return size;
    }
};
int getSizeRecursive(const node* &root){ // line 1
    if(root->children.size()==0)
        return 1;

    int size = 0;
    for(const node* &child : root->children) // line 2
        size  += getSizeRecursive(child);
    return size+1;
}
int main(){
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    vector<int> v{10,20,-1,30,50,-1,60,-1,-1,40,-1,-1};
    GenericTree t(v); // node that tree has been created 
    cout << t.size << endl;
    cout << getSizeRecursive(t.root) << endl;
    return 0;
}

What i can understand from this is that compiler is not able to bind the reference to pointer to const node to const pointer to node but my question is that why it is taking t.root as const pointer to node whereas in actual it is just a pointer to node(see line no 3).

I am novice in c++. Any help would be appreciated.

EDIT: The reason i have used const* & root is because i did not want to pass a copy of root to getSizeRecursive but during that since i have passed by reference i have used const so that this reference just only reads the root pointer and not modify it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

想你的星星会说话 2025-02-19 15:56:16

让我们来看看根据情况下每个错误的原因。此外,我将尝试通过步骤解释事情。

案例1

在这里,我们考虑由于该陈述而引起的第一个错误:

for(const node* &child : root->children)

现在要了解为什么由于上述语句而遇到错误,让我们以逐步的方式理解每个术语的含义:

步骤1: <

<代码> root 是A non-const lvalue参考 to const node 的非const指针。这意味着我们允许我们更改root ref的指针(因为我们有nonconst lvalue ref),但是我们不允许更改实际的node。该指针指向的对象。

步骤2

root-&gt; roots is const vector&lt; node*&gt;,因为我们不允许更改node node < /代码>指针指向的对象如上所述。基本上,对象的指向本身就是const,这又意味着其数据成员也被视为const。作为儿童是数据成员,因此将其视为const,因此root-&gt; children is const vector&lt; node* &gt;

请注意,此步骤的结论是,我们有一个带有类型节点*的元素的const向量。

步骤3

现在,const node*&amp; child表示child non-const lvalue引用 nonconst指针 const Node 。同样,这意味着我们允许我们更改向量内部的指针。但这是一个问题,因为我们从上面的步骤2中学到了const vector&lt; node*&gt;,这意味着我们不应允许我们更改位于向量内部的指针。因此,您会得到上述错误。

解决案例1

solve 的解决方案,您需要确保通过添加 低级const来更改位于const vector内部的指针如下所示:

//-------vvvvv--------------------------->const added here
for(node*const &child : root->children)

上面的作品是因为现在child lvalue引用对非Conconst节点对象的const指针

情况2

在这里,我们考虑由于表达式引起的第二个错误:

getSizeRecursive(t.root)

此处传递的参数t.rootnode*,而参数为const node*&amp ;。现在,传递的参数被隐式转换为const Node*,但转换的结果将是一个rvalue。但是,由于参数root nonconst lvalue参考 to const node 的非const指针它不能绑定到rvalue。

这基本上是与您将使用的错误相同的错误:

node *ptr;
const node*& ref = ptr; //will produce the same error saying: error: cannot bind non-const lvalue reference of type ‘const int*&’ to an rvalue of type ‘const int*’

解决情况2的解决方案

基本上,给定类型t可以绑定到t&amp;t const&amp; < /code>虽然给定类型const t可以绑定到t const&amp;。在您的示例中,传递的参数为node*这意味着它可以绑定到node*&amp;以及node*const&amp;。 。

为了解决此问题,您可以将lvalue引用到const lvalue参考文献,如下所示:

node *ptr;
//---vvvvv--------------->const added here
node*const& ref = ptr;

在您的示例中,这意味着:

//------------------------vvvvv--------->const added here
int getSizeRecursive(node*const &root){ // line 1

Let's see the reason for getting each of the error on case by case basis. Moreover, i'll try to explain things in steps.

Case 1

Here we consider the 1st error due to the statement:

for(const node* &child : root->children)

Now to understand why we get error due to the above statement, let's understand the meaning of each term in step by step manner:

Step 1:

root is a non-const lvalue reference to a non-const pointer to const node. This means that we're allowed to change the pointer to which root refers(since we've a nonconst lvalue ref) but we're not allowed to change the actual node object to which that pointer is pointing.

Step 2

root->children is const vector<node*> since we're not allowed to change the node object to which the pointer is pointing as discussed in step 1 above. Basically, it is as if the pointed to object is itself const which in turn means its data members are treated as const as well. And as children is a data member so it is treated as const and thus root->children is const vector<node*>.

Note the conclusion of this step is that we have a const vector with elements of type node*.

Step 3

Now, const node* &child means that child is a non-const lvalue reference to a nonconst pointer to a const node. Again, this means that we're allowed to change the pointer residing inside the vector. But this is a problem because we learnt from step 2 above that we've a const vector<node*> meaning that we should not be allowed to change the pointer residing inside the vector. And hence you get the mentioned error.

Solution to case 1

To solve this you need to make sure that there is no way to change the pointer residing inside the const vector by adding a low-level const as shown below:

//-------vvvvv--------------------------->const added here
for(node*const &child : root->children)

The above works because now child is a lvalue reference to a const pointer to a nonconst node object.

Case 2

Here we consider the 2nd error due to the expression:

getSizeRecursive(t.root)

Here the passed argument t.root is a node* while the parameter is a const node* &. Now, the passed argument is implicitly convertible to const node* but result of that conversion will be an rvalue. But since the parameter root is an nonconst lvalue reference to a non-const pointer to const node it cannot be bound to an rvalue.

This is basically the same error that you will get using:

node *ptr;
const node*& ref = ptr; //will produce the same error saying: error: cannot bind non-const lvalue reference of type ‘const int*&’ to an rvalue of type ‘const int*’

Solution to Case 2

Basically, a given type T can be bound to T& or T const& while a given type const T can be bound to T const&. And in your example, the passed argument is node* meaning it can be bound to both node*& as well as node*const&.

To solve this you can make the lvalue reference to a const lvalue reference as shown below:

node *ptr;
//---vvvvv--------------->const added here
node*const& ref = ptr;

In your example, this means:

//------------------------vvvvv--------->const added here
int getSizeRecursive(node*const &root){ // line 1

Working demo

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文