为什么从外部访问本地声明的变量有效?

问题描述

在树中,在接受输入时(在 takeInput 函数内),树节点是使用动态分配创建的,但我尝试静态分配,但由于树节点是在本地函数内声明的,因此它不应该工作,因为它是一个局部变量(我期待一个错误)。但是为什么在那之后我还能打印出来:

注意:此代码递归地接受输入(可能不是最好的方法

#include<bits/stdc++.h>
using namespace std;
template <typename T>
class treeNode{
    public:
    T data;
    vector <treeNode<T>> children;
    treeNode(T data){
        this->data=data;
    } 
};
treeNode<int> takeinput(){
    int rootdata;
    cout<<"Enter Node"<<endl;
    cin>>rootdata;
    // treeNode<int>* root= new treeNode<int>(rootdata);

    treeNode<int> root(rootdata);   //Static Allocation

    cout<< "Enter Number of children of "<<rootdata<<endl;
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        treeNode<int> child = takeinput();
        root.children.push_back(child);
    }
    return root;
}
void printTree(treeNode<int> root){
    cout<<root.data<<": ";
    for(int i=0;i<root.children.size();i++){
        cout<<root.children[i].data<<",";
    }
    cout<<endl;
    for(int i=0; i<root.children.size();i++){
        printTree(root.children[i]);
    }
}
int main(){
    treeNode<int> root= takeinput();
    printTree(root);
    return 0;
}

以下代码使用动态分配:

#include<bits/stdc++.h>
using namespace std;

template <typename T>
class TreeNode{
    public:
    T data;
    vector <TreeNode<T>*> children;
    TreeNode(T data){
        this->data=data;
    }
};
TreeNode<int>* takeinput(){
    int rootdata;
    cout<<"Enter node"<<endl;
    cin>>rootdata;
    TreeNode<int>* root=new TreeNode<int>(rootdata);
    cout<<"Enter number of children of "<<rootdata<<endl;
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        TreeNode<int>* child=takeinput();
        root->children.push_back(child);
    }
    return root;
}
void printTree(TreeNode<int>* root){
    if (root == NULL){
        return;
    }
    cout<< root->data<<" :";
    for(int i=0;i<root->children.size(); i++){
        cout<<root->children[i]->data<<",";
    }
    cout<<endl;
    for(int i=0;i<(*root).children.size();i++){
        printTree(root->children[i]);
    }
}
int main(){
    TreeNode<int>* root = takeinput();
    printTree(root);
    return 0;
}

解决方法

你的代码相当于

jdbc:h2:./data/testdb;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=10990

A foo() { A a; a = bar(); return a; } 只是被复制到返回值中(那个 copy might be avoided 也是)。将 a 替换为 A,语义保持不变。

为什么是动态代码?

我猜使用动态分配的代码版本可能被编码为类似

treeNode<int>

struct A { std::vector<A> vecA; }; 的递归定义,因为当 A 被声明时,vecA 是一个不完整的类型。但情况不再如此,这正式进入 C++17 (尽管它也适用于早期版本的某些编译器),其中一些 STL 容器可以处理不完整的类型。因此它使用了形式

A

存储指向子节点的指针和代码,类似于熟悉的 LinkedList Node 数据结构定义

vector <TreeNode<T>*> children;

结论

堆栈分配通常是首选可能,因为它比堆路由更快。此外,除非使用智能指针,否则动态分配的代码会带来内存管理的麻烦。您的代码不需要它。使用您的示例的堆栈分配路线,让 struct Node { int data; Node* next; // The TreeNode stores a vector of pointers instead. }; 负责维护动态数组。