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

Why accessing variable declared locally from outside is working?

在树中,在接受输入时(在 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;
}

您的代码等同于

A foo() {
    A a;
    a = bar();
    return a;
}

a 只是复制到 return 值(copy might be avoided 也是)。将 A 替换为 treeNode<int>,语义保持不变。

为什么要动态代码?

我猜想使用动态分配的代码版本可能是在考虑类似

的情况下编写的
struct A {
    std::vector<A> vecA;
};

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

vector <TreeNode<T>*> children;

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

struct Node {
    int data;
    Node* next; // The TreeNode stores a vector of pointers instead.
};

结论

如果可能通常首选堆栈分配,因为它比堆路由更快。此外,除非使用智能指针,否则具有动态分配的代码会带来内存管理的麻烦。您的代码不需要它。使用您的示例的堆栈分配路径,让 std::vector 负责维护动态数组。