C++ vector reallocation: why does vtNode[p].child[c] = newNode() cause unexpected behavior?

Правка en1, от nhan0123456, 2026-08-08 08:46:34

Unexpected behavior when modifying a vector while calling push_back

I have a problem with the following Trie implementation.

Code 1 — RE

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

struct Trie {
    struct Node {
        int child[2];
        long long sum, val;

        Node() {
            child[0] = child[1] = -1;
            sum = val = 0;
        }
    };

    vector<Node> vtNode;
    int root;

    Trie() {
        root = newNode();
    }

    int newNode() {
        int id = (int)vtNode.size();
        vtNode.push_back(Node());
        return id;
    }

    int getBit(long long x, int i) {
        return (x >> i) & 1;
    }

    void addNum(long long x) {
        int p = root;

        for (int i = 32; i >= 0; --i) {
            int c = getBit(x, i);

            if (vtNode[p].child[c] == -1) {
                cerr << vtNode[p].child[c] << "\n";

                vtNode[p].child[c] = newNode();

                cerr << vtNode[p].child[c] << "\n";
            }

            p = vtNode[p].child[c];
        }
    }
};

int main() {
    Trie trie;
    trie.addNum(12345);

    return 0;
}

Code 2 — works correctly

The only difference is that I store the result of newNode() in a local variable before modifying vtNode[p].child[c]:

void addNum(long long x) {
    int p = root;

    for (int i = 32; i >= 0; --i) {
        int c = getBit(x, i);

        if (vtNode[p].child[c] == -1) {
            cerr << vtNode[p].child[c] << "\n";

            int id = newNode();
            vtNode[p].child[c] = id;

            cerr << vtNode[p].child[c] << "\n";
        }

        p = vtNode[p].child[c];
    }
}

The second version works as expected, while the first version gives unexpected results.

For the first version, cerr prints -1 again after newNode():

-1
-1
-1
...

while the second version prints increasing positive indices.

My question

Why does this happen?

I initially thought these two pieces of code were equivalent:

vtNode[p].child[c] = newNode();

and

int id = newNode();
vtNode[p].child[c] = id;

Is this related to vector::push_back() causing reallocation and invalidating something?

I would like to understand what happens during the evaluation of vtNode[p].child[c] = newNode(); and why storing the return value in a local variable changes the behavior.

Теги trie, tree, vector, implementation, index

История

 
 
 
 
Правки
 
 
  Rev. Язык Кто Когда Δ Комментарий
en1 Английский nhan0123456 2026-08-08 08:46:34 2614 Initial revision (published)