>

아래와 같이 나무를 채우려 고합니다. m  입력 수와 s 입니다  헤드 노드의 데이터입니다. c  는 헤드 노드이고 뒤에 나오는 입력은 부모-자식 노드입니다. 각 노드에는 하위 목록이 있습니다.

지금 addNode 를 불러  항상 나무 꼭대기에서 시작하는 것은 내가하고있는 일에 느립니다. 대신, 나는 addNode 를   to 에 대한 참조를 반환  트리에 추가하는 노드입니다. 나는지도 iNode 를 유지  와이즈 비츠   to - TreeN 에 대한 참조를 전달할 수 있도록   from 에 노드  헤드 노드를 전달하는 대신

addNode 때 의 벡터 크기가 조정되고 객체의 객체가 메모리의 새 벡터에 복사되고 TreeN 에있는 노드에 대한 참조가 복사됩니다  메모리 할당을 해제해야합니다. Cpp를 처음 접했을 때는 확실하지 않습니다.

원하는대로 작동하게하려면 어떻게해야합니까?

iNode

입력 :

class TreeN {
public:
    int d;
    vector<TreeN> chld;
    bool operator==(const TreeN &o) {
        return o.d == d;
    }
};
TreeN& addNode(TreeN &root, int &from, int &to) {
    cout << "f: " << from << " t: " << to << " p: " << root.d << endl;
    if (root.d == from) {
        root.chld.push_back(TreeN{to});
        return root.chld[root.chld.size() - 1];
    }
    else {
        for(auto &c : root.chld) {
            return addNode(c, from, to);
        }
    }
}
int main(int argc, const char** argv) {
    int m, s;
    cin >> m >> s;
    TreeN c = {s, vector<TreeN>{}};
    map<int, TreeN&> iNode;
    iNode.insert(pair<int, TreeN&>(c.d, c));
    while (m--) {
        int a, b;
        cin >> a >> b;
        map<int, TreeN&>::iterator itA = iNode.find(a);
        map<int, TreeN&>::iterator itB = iNode.find(b);
        if (itA != iNode.end()) {
            cout << "here " << itA->first << endl;
            TreeN &n = addNode(itA->second, a, b);
            cout << n.d << endl;
            if (itB == iNode.end()) iNode.insert(pair<int, TreeN&>(b, n));
        } else {
            iNode.insert(pair<int, TreeN&>(b, addNode(c, a, b)));
        }
    }
    printTree(c);
}

이 코드는 실패하고 다음 출력을 제공합니다.

4 1
1 2
1 3
2 3
3 2

here 1 f: 1 t: 2 p: 1 2 here 1 f: 1 t: 3 p: 1 3 here 2 f: 2 t: 3 p: 0 (should say 2) Segmentation fault (core dumped)
  • 답변 # 1

    코드의 기능과 방법을 이해하려고하지 않습니다.
    이상한 곳에서 참조를 사용하면 읽고 이해하기가 어려워졌습니다. 이 코드에서는 변수의 수명이 해당 변수를 가리키는 참조 수명을 초과하는지 여부를 추적하기가 어렵습니다.

    초보자 인 경우 참조는 함수 인수로만 사용하십시오.

    어쨌든 여기에 정의되지 않은 동작이 나타납니다 :

    TreeN& addNode(TreeN &root, int &from, int &to) {
        cout << "f: " << from << " t: " << to << " p: " << root.d << endl;
        if (root.d == from) { // consider this false
            root.chld.push_back(TreeN{to});
            return root.chld[root.chld.size() - 1];
        }
        else {
            for(auto &c : root.chld) {// root.chld is empty
                return addNode(c, from, to); // this is weird and wrong - but not a source of crash
            }
        }
        // then you can reach this place and there is no return statement
        // leading to UB
        // I'm pretty sure compilers warns you about this problem.
    }
    
    
    또한이 마지막 루프는 의미가 없습니다. 첫 번째 반복은 루프 실행을 종료합니다. 방어적인 의도는 아닙니다.

    와이즈 비즈

    가능합니다. 벡터는 일부 예약을 할당하고 (용량 참조) ​​크기가 커지면 새 메모리 용량이 할당되고 값이 새 버퍼로 복사/이동됩니다. 벡터의 항목에 대한 참조가 유효하지 않게 할 수 있습니다.
    그러나 : 나는 당신이 그 참조를 더 이상 저장하지 않고 다음 가능한 크기를 조정하여 문제가되지 않는다고 생각합니다.

    I think what happens is when a TreeN's vector resizes, the objects in it are copied to a new vector in memory and the reference to the nodes I had in iNode are to now deallocated memory. I'm not sure though, fairly new to Cpp.

관련 자료

  • 이전 regex - 쉼표없이 숫자를 반환하는 정규식
  • 다음 javascript - 하단에서 시작하여 div에 요소를 추가 하시겠습니까?