【问题标题】:Address of This changes during execution. why? [duplicate]This的地址在执行期间发生变化。为什么? [复制]
【发布时间】:2020-10-08 09:11:10
【问题描述】:

如你所见,从我的输出结果来看,this的地址在执行过程中发生了变化,我想我可以利用指针比较来实现一个树系统,而不需要里面有一个子列表节点和我希望能够比较节点列表中每个元素的父节点以获取更多功能。但它的主要问题是指针地址更改,任何人都可以帮助我了解我缺少什么。

 struct Nodo{
    Nodo* parent=0;
    const char* identity;
    Component* component;
    Nodo()=default;
    Nodo(const char* uid){
        identity=uid;
    }
    Nodo(Nodo* ptr,const char* uid){
        parent=ptr;
        identity=uid;
        std::cout << "\n Address given to " << uid << "  " << ptr <<std::endl;
    }
    void Add(const char* uid,std::vector<Nodo>& objects){
        std::cout << "\n Add call in " << identity << " address sent "<< this <<std::endl;
        objects.emplace_back(Nodo(this,uid));
    }
    void GrapthUI(std::vector<Nodo>& nodes){
        ImGui::PushID(this);
        if(ImGui::TreeNode(identity)){
            ImGui::TreePop();
            ImGui::Indent();
            for(int indx=0; indx<nodes.size(); indx++){
                if(&nodes[indx]!=this){
                    if(nodes[indx].parent==this){
                        nodes[indx].GrapthUI(nodes);
                    }
                }
            }
            ImGui::Unindent();
        }
        ImGui::PopID();
    }
 }

std::vector<Nodo> node;
Main(){//in c++ file.
    node.emplace_back(Nodo("root"));
    node[0].Add("Airplane",node);
    node[0].Add("Ball",node);
    node[1].Add("Car",node);
}

输出:

 Add call in [ root ] address sent 0C8FCF88
 Address given to [ Airplane ] 0C8FCF88

 Add call in [ root ] address sent 0C920C68
 Address given to [ Ball ] 0C920C68

 Add call in [ Airplane ] address sent 0C916DE4
 Address given to [ Car ]  0C916DE4

我希望 AirplaneBall 的父指针具有与 Root 相同的地址 [0C8FCF88]但它是不同的。我在这里看到了与此类似的同名帖子,但它对我没有帮助,也不完全涉及我的问题。

【问题讨论】:

  • 您是否考虑到std::vector 可以在其增长时重新定位其成员?
  • vector 在重新分配内存时使所有迭代器失效
  • 不相关,但是只要你有一个节点同时满足这两个要求,GraphtUI 中的递归调用就会导致无限递归。
  • 你能给我一个会导致这种情况的案例吗?我打算从单个 node[0] -(root) 节点调用 GraphUI。但可能还有其他我遗漏的案例。

标签: c++ memory-management


【解决方案1】:

如果向向量中添加一个元素,结果大小超过其当前容量,则向量需要分配更多内存。它分配一个新的内存块并将所有现有元素移动到该内存块中,然后添加新元素。然后释放旧的内存块。

如果你想有稳定的地址,你可以使用std::vector&lt;std::unique_ptr&lt;Nodo&gt;&gt;

【讨论】:

  • ... 除了子节点将通过parent 指向unique_ptr 的附加指针。严格来说,您应该使用shared_ptr resp。 weak_ptr 在这种情况下,但我们不知道 OP 将 parent 指针用于什么。
  • 我不认为这是一个问题,向量“拥有”这棵树,看起来他计划将所有孩子添加到向量中。但是对于 OP 来说,阅读 C++ 中可用的智能指针并思考什么最适合他的用例是绝对值得的。
  • 是的,因此是“严格来说”部分。如果父指针仅用于提供节点标识,我会允许此代码通过代码审查。
  • 明白感谢您的澄清,我没有意识到 std::vector 就是这种情况,看来我需要重新考虑一下。
【解决方案2】:

这不是问题。这种行为是正常的。开始时的 std::vector 分配一块特定维度的内存。如果分配的内存足够,则将元素添加到向量时,地址是相同的(还要注意,如果内存足够但接近限制,则执行可能会重新定位整个向量),如果内存不足,所有向量都被重新定位到更大的新内存空间中,并且释放了先前的内存区域。当您从向量中删除一个元素时,也会发生这种行为,该元素会自行调整其大小以节省内存。

正如Cppreference push_back 所说:

如果新的 size() 大于 capacity() 则所有迭代器和 引用(包括过去的迭代器)无效。 否则只有过去的迭代器无效。

【讨论】:

  • “这不是问题。”鉴于他的代码示例,这是错误的。他为一棵树建模,里面会有无效的指针。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-06
相关资源
最近更新 更多