【问题标题】:Scope of an Object in a Loop循环中对象的范围
【发布时间】:2016-11-16 20:08:43
【问题描述】:

我有一个简单的算法,它返回一个列表列表,其中每个内部列表包含二叉树不同级别的节点。我无法理解如何“重置”我的内部列表的范围(例如,见下文)。

我的树是一棵简单的玩具树,如下所示:

struct Node {
    int data;
    Node *left, *right;
}

我使用了一个简单的 bfs,它应该返回一个列表列表。我尝试在每个循环上创建一个新列表,但我不确定如何“清除”列表并开始一个新列表。

std::vector< std::vector<Node *> > build_lists(Node *root) {
    std::vector< std::vector<Node *> > result;

    Node *newline = new Node { std::numeric_limits<int>::min(), nullptr, nullptr };

    std::deque<int> q;
    q.push_back(root);
    q.push_back(newline);


    Node *tmp;
    std::vector<Node *> inner;    // HERE IS WHERE IS SET THE FIRST INNER VECTOR
    while(!q.empty()) {
        tmp = q.front();
        q.pop_front();
        if (tmp == newline) {
            result.push_back(inner);
            std::vector<Node *> inner; // HERE IS WHERE I TRY TO ''RESET'' THE VECTOR
            if (!q.empty())
                q.push_back(newline);
        } else {
            inner.push_back(tmp);
            if (tmp->left)
                q.push_back(tmp->left);
            if (tmp->right)
                q.push_back(tmp->right);
        }
    }
}

显然,我没有理解范围和一些基本的语言特性。如果有人能帮助我指出正确的方向,我将不胜感激。

【问题讨论】:

  • 没有投反对票。通过列表,您的意思是 inner?
  • @gsamaras 是的。抱歉,我猜这里是矢量。
  • 声明第二个对象名称“inner”对第一个对象没有任何作用——它只是意味着堆栈上有两个同名对象(在C ++,但通常不赞成,因为它会引起混乱)。要重置矢量,您应该改为调用 inner.clear();
  • @JeremyFriesner 我猜这是个愚蠢的问题,但为什么inner.clear() 不清除我推到result 向量上的向量?
  • 因为 push_back 制作了 inner 的副本并将该副本推送到结果向量中。 (C++ 与 Java 等其他语言的不同之处在于,Java 中的所有内容都通过引用传递;在 C++ 中,您通常也按值传递对象,这涉及制作对象的副本)

标签: c++ c++11 vector scope breadth-first-search


【解决方案1】:

您不能通过再次声明变量来重置变量,这就是您的代码正在执行的操作。您现在有了第二个同名变量,在第二个变量的持续时间内,该名称指向第二个变量。

相反,您需要使用一种方法来清除第一个变量。

vector 确实有一个 method to reset it's contents - vector::clear

你应该这样做:

result.push_back(inner);
// std::vector<Node *> inner;
inner.clear();

如果您需要清除已推入向量中的内容,您可以这样做:

vector< vector< int > > vvi;
vector< int > vi;
vi.push_back(1); // fill
vii.push_back(vi); // vii has a copy of vi as it is now.
auto & _v = vii[0]; // fetch a reference to the copy
_v.clear(); // clear it
vii[0].clear(); // same in one step
assert( vii[0].size() == 0 ); // still contains a vector at index 0 but it's empty

尽管您将清除 指针的向量 - 正如其他人指出的那样 (ha) 您需要非常小心不要“丢失”指针。

例如,这会很糟糕:

vector< int* > x;
x.push_back( new int(4) );
x.clear(); // leak

【讨论】:

    【解决方案2】:

    为了使对象超出范围,必须在 INSIDE 循环中创建它,例如:

    while(1) {
      std::vector<int> v;
      ...
      // at that point 'v' will go out of scope and thus destroyed
    }
    

    但是,当你这样做时:

    std::vector<int> v;
    while(1) {
      ...
      // 'v' is always the same at this point
    }
    

    您可以使用std::vector::clear() 重置您的向量,但要小心,因为您使用的是指针。除非您跟踪指向的对象,否则仅清除向量会导致 悬空指针,因此 未定义的行为,您不希望这种情况发生。

    如果您需要释放指针指向的内存,那么您应该首先删除指针指向的对象,然后然后清除向量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-26
      • 1970-01-01
      • 2018-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-11
      相关资源
      最近更新 更多