C++ 我从指针获取未初始化的对象

C++ 我从指针获取未初始化的对象,c++,pointers,sfml,C++,Pointers,Sfml,因此,我在获取使用SFML形状的指针时遇到了一些困难。我不确定这是否与SFML有关,或者我是否做错了什么 在Draw()中,x(一个控制窗口)不包含有效值,它只显示“?”,如下所示。但是,m_控件(贴图)包含控件对象的正确值 我对C++很陌生,所以任何帮助都会被大大理解。 例外情况 主要 矢量窗口控件; 无效提款(); int main() { 矩形形状rect(Vector2f(120120)); WindowControl WindowControl(nullptr,0); 控件testCo

因此,我在获取使用SFML形状的指针时遇到了一些困难。我不确定这是否与SFML有关,或者我是否做错了什么

在Draw()中,x(一个控制窗口)不包含有效值,它只显示“”,如下所示。但是,m_控件(贴图)包含控件对象的正确值

我对C++很陌生,所以任何帮助都会被大大理解。

例外情况 主要
矢量窗口控件;
无效提款();
int main()
{
矩形形状rect(Vector2f(120120));
WindowControl WindowControl(nullptr,0);
控件testControl(&windowControl,1);
testControl.SetShape(&rect);
AddControl(testControl);
windowControl.向后推(windowControl);
返回0;
}
窗口控制
类窗口控件:控件
{
公众:
WindowControl(WindowControl*WindowControl,uint64\u t uint64)
:控件(窗口控件,uint64)
{
}
无效添加控制(控制)
{
m_controls.insert_或赋值(control.GetId(),control);
m_controlPtrs.推回(和控制);
}
向量*GetControls()
{
返回和维护控制PTR;
}
私人:
地图m_控件;
向量m_控制ptrs;
};
用于(自动x:windowControls)
{
向量*controlPtrs=x.GetControls();
窗口->绘图(x.GetControl(0)->GetShape());
}

您的问题是将局部变量的指针添加到
m_controlPtrs

void AddControl(Control control)
{
    m_controlPtrs.push_back(&control);
}
在这里,您可以复制一份
控件
,然后将其地址添加到
向量
中。函数返回的那一刻,对象就超出范围,内存指向未初始化的垃圾

您可能需要更新
AddControl
以获取
控件&

当前位置我提到的可能会解决您的问题,可能是无限期的,但您的设计仍然不太好。任何时候你有一个
控件
,它的寿命不会超过
m_controlPtrs
,你都会遇到同样的问题。您的代码现在很小,但这最终可能会变成一场需要修复的噩梦。您可能应该更新
m_controlPtrs
,以共享(或获取)
控件的所有权,这样就不会出现此问题


最简单的方法是将
m_controlPtrs
声明为
std::vector
,但这是您应该考虑的问题。

这里有一个问题:

void AddControl(Control control)
{
    m_controls.insert_or_assign(control.GetId(), control);
    m_controlPtrs.push_back(&control);
}
添加参数
控件的地址,该地址在函数结束时被销毁。看起来您想要添加添加到地图的副本的地址,如下所示:

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()]); 
}
虽然这并不理想,因为如果发送相同的
控件两次,它将只在映射中出现一次(更新),但在指针向量中出现两次。您可以使用
insert\u或\u update
返回的pait来修复:

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;
}
vector&GetControls()
{
返回m_controlPtrs;
}

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

这可能是由于复制对象而不是将指针添加到向量造成的。该本地对象超出范围,并且您得到了一个错误的指针:FYI
m_controlPtrs.push_back(&control)
是错误的,尽管使用
控件&
只意味着生成的指针基于另一个对象,而
向量
无法控制该对象的生存期。除非您知道所有此类
控件
s的作用域始终超出容纳它们的
窗口控件
,否则您没有解决问题,只是将其延迟。似乎转移
控件的所有权
(因此
向量
存储
控件
,而不是
控件*
),或者使用
共享的ptr
(因此创建者和
向量
共享所有权,并且生命周期与两者需要的时间一样长),都是更好的选择。
void AddControl(Control control)
{
    m_controls.insert_or_assign(control.GetId(), control);
    m_controlPtrs.push_back(&control);
}
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()]); 
}
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;
}