【问题标题】:Automatic object changes memory location自动对象更改内存位置
【发布时间】:2016-06-05 01:47:26
【问题描述】:

首先,让我们考虑一下我目前正在从事的一个项目的以下摘要。这是标题:

class GUI {
public:
    GUI& Initialize();
    void DrawGUI(float width, float height);

private:
    Model quad;
    Shader sh;
    Camera cam;
};

虽然这是 cpp 文件:

GUI& GUI::Initialize() {
    quad.Initialize().LoadModel("Resources/quad.obj");
    sh = Shader().Initiliaze();
    sh.models.push_back(&quad);
    return *this;
}

void GUI::DrawGUI(float width, float height) {
    quad.SetScale(width, height, 0);
    sh.RenderModels();
}

在直接解决问题之前,需要先解释一下。 Shader 对象 sh 将指向特定数量模型的指针存储在向量 vector<Model*> models 中。这些模型可以使用RenderModels 方法进行渲染。 在初始化过程中,GUI 通过quad 的地址&quadquad 添加到sh.models。然后DrawGUI 方法可用于缩放quad 并将其绘制在屏幕上。

问题:

在我的主函数中使用DrawGUI时,缩放没有效果!

这是由于我希望有人能为我解开的“神秘”行为。我已经知道问题的根源,但我无法理解其背后的原因。 虽然SetScale 函数修改了quad 的尺寸,但这不会影响渲染,因为(我在调试时已经验证过)&quadsh.models[0] 在调用DrawGUI 时具有不同的值。特别是,quad 在初始化和绘图调用之间的某个时间点更改了它的地址,而我没有任何干预。一个小改动解决了这个问题,然后缩放发生了:

void GUI::DrawGUI(float width, float height) {
    sh.models[0].SetScale(width, height, 0);
    sh.RenderModels();
}

但这并不能帮助我理解为什么首先会出现问题。事情变得更不清楚了,虽然当GUI 被声明为使用自动存储时会出现问题,即GUI gui;,但当我在堆上分配GUI 时它不会出现。事实上quad 不会更改地址,保持与sh.models[0] 相同,并且一切正常。

为什么两种分配方式之间的行为不同?我缺少关于自动分配的东西吗?为什么quad地址变了?

【问题讨论】:

  • 如果quad 的地址发生了莫名其妙的变化,则表明您有新的GUI 对象在您不期望的情况下被实例化。例如。如果你 push_backGUI 到一个容器,它将创建它的副本。虽然您没有显示足够的代码来知道是否是这种情况,但是如果您在 GUI 构造函数中放置一个 cout ,您应该能够轻松判断是否发生了这种情况。
  • 您是否尝试过使用已删除的复制构造函数?我的猜测是您将 GUI 作为副本传递给某个函数或其他东西。
  • @JonathanPotter 我刚刚尝试了cout 技巧。我只有一张印刷品……
  • 您是否添加了显式复制构造函数?
  • 删除拷贝构造函数和赋值运算符,重新编译工程。我敢打赌,你会看到编译错误。

标签: c++ memory-management raii temporary-objects


【解决方案1】:

使用最新的 cmets,问题现在很清楚了。 OP的代码中存在以下行:

GUI gui = GUI().Initialize();

Initialize最重要的部分是:

GUI& GUI::Initialize() {
    // ...
    return *this;
}

因此,GUI 对象的复制构造函数被调用。在没有任何用户提供的代码的情况下,使用默认的复制构造函数——并且由于 OP 还提到了指针,这些指针被复制为默认复制构造函数的一部分。但是没有人复制这些对象!事实上,没有人在新对象上调用Initialize

从给定的 sn-ps 解决方案尚不清楚,但有几件事是显而易见的:

  • 不要使用Initialize函数。使用构造函数,这就是它的用途。
  • 仔细考虑复制您的对象。如有疑问,请删除复制构造函数和赋值运算符。
  • 不要使用原始指针来管理对象,这就是智能指针的用途。在智能指针中,您的首选应该是unique_ptr

【讨论】:

  • 好的,现在我明白了...我会尽量遵循您的指导,谢谢!
猜你喜欢
  • 2022-07-23
  • 1970-01-01
  • 1970-01-01
  • 2019-08-06
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-07
相关资源
最近更新 更多