我从指针中得到一个非初始化的对象

I get an uninitialized object from a pointer

本文关键字:一个 初始化 对象 指针      更新时间:2023-10-16

所以我有一些麻烦,让指针与SFML形状一起使用。我不确定这是否与SFML有关,还是我做错了什么。

在draw((x(a controlWindow (中不包含有效值,它仅显示" ??? ",如下所示。但是,M_Controls(MAP(包含控制对象的正确值。

我是C 的新手,因此对任何帮助都将不胜感激。

异常

Exception thrown at 0x60B26EE5 (sfml-graphics-2.dll) in OokiiUI.exe: 0xC0000005: Access violation reading location 0x00000000.

vector<WindowControl> windowControls;
void Draw ();
int main ()
{
    RectangleShape rect(Vector2f(120,120));
    WindowControl windowControl(nullptr,0);
    Control testControl(&windowControl,1);
    testControl.SetShape(&rect);
    windowControl.AddControl(testControl);
    windowControls.push_back(windowControl);

    return 0;
}

windowcontrol

class WindowControl : Control
{
public:
    WindowControl ( WindowControl * windowControl, uint64_t uint64 )
        : Control ( windowControl, uint64 )
    {
    }
    void AddControl(Control control)
    {
        m_controls.insert_or_assign(control.GetId(), control);
        m_controlPtrs.push_back(&control);
    }
    vector<Control*>* GetControls()
    {
        return &m_controlPtrs;
    }
private:
    map<uint64_t, Control> m_controls;
    vector<Control*> m_controlPtrs;
};

绘制

for (auto x : windowControls)
{
    vector<Control*> *controlPtrs = x.GetControls();
    window->draw(x.GetControl(0)->GetShape());
}

这里有一个问题:

void AddControl(Control control)
{
    m_controls.insert_or_assign(control.GetId(), control);
    m_controlPtrs.push_back(&control);
}

您添加函数结束时被破坏的参数control的地址。看起来您想添加 copy 的地址,然后将其添加到map

void AddControl(Control control)
{
    m_controls.insert_or_assign(control.GetId(), control);
    // don't use the parameter here, use the copy you put in the map
    m_controlPtrs.push_back(&m_controls[control.GetId()]); 
}

尽管这不是理想的选择,因为如果您两次发送相同的 control,但它将仅在地图中出现一次(更新(,但在Pointers的向量中两次。您可以使用 insert_or_update返回的馅饼来修复:

void AddControl(Control control)
{
    auto [iter, was_inserted] = m_controls.insert_or_assign(control.GetId(), control);
    // only add to vector if it was not in the map before
    if(was_inserted)
        m_controlPtrs.push_back(&iter->second);
}

旁注:

在这种情况下返回参考而不是指针是更惯用的:

vector<Control*>& GetControls()
{
    return m_controlPtrs;
}

这也打破了封装,因此可能值得考虑如何避免直接访问对象的内部。

您的问题是您将本地变量的指针添加到m_controlPtrs

void AddControl(Control control)
{
    m_controlPtrs.push_back(&control);
}

在这里,您可以将Control的副本添加到vector中。函数返回的那一刻,您的对象就脱离了范围,而内存则指向非初始化的垃圾。

您可能想更新AddControl以服用Control&

@shadowranger在评论中提出了一个很好的观点:我提到的内容可能会无限期地解决您的问题,但您的设计并不是很棒。每当您有一个Control时,它不会超过m_controlPtrs,您就会遇到同样的问题。您的代码现在很小,但最终可能会变成一场噩梦以修复。您可能应该更新m_controlPtrs以共享(或获取(Control的所有权,因此不会发生此问题。

最简单的方法是将m_controlPtrs称为std::vector<std::shared_ptr<Control>>,但这是您应该考虑的东西。