为什么在第一次调用cout之后,drawManifestoGlobal中的值会发生变化?看来canvas.panel.drawManifestoGlobal被破坏了-为什么?

我该如何解决?

#include <iostream>

class DrawManifestoGlobal {
public:
    int value = 2;
};

class Panel {
public:
    void setDrawManifestoGlobal(DrawManifestoGlobal & _drawManifestoGlobal);
    DrawManifestoGlobal * drawManifestoGlobal;
};

class Canvas {
public:
    Canvas() {};
    Canvas(DrawManifestoGlobal _drawManifestoGlobal);
    DrawManifestoGlobal drawManifestoGlobal;
    Panel panel;
};


class SerDe {
public:
    Canvas doSerDe();
};

Canvas SerDe::doSerDe() {

    DrawManifestoGlobal drawManifestoGlobal;
    drawManifestoGlobal.value = 99;
    Canvas canvas(drawManifestoGlobal);

    return canvas;
}

Canvas::Canvas(DrawManifestoGlobal _drawManifestoGlobal) {
    drawManifestoGlobal = _drawManifestoGlobal;
    panel.setDrawManifestoGlobal(drawManifestoGlobal);
}

void Panel::setDrawManifestoGlobal(DrawManifestoGlobal &_drawManifestoGlobal) {
    drawManifestoGlobal = &_drawManifestoGlobal;
}

int main () {
    SerDe serde;
    Canvas canvas;
    canvas = serde.doSerDe();

    std::cout << canvas.panel.drawManifestoGlobal->value << std::endl; // prints 99
    std::cout << canvas.panel.drawManifestoGlobal->value << std::endl; // prints 0 (!!!)
}

关于实现要求:Canvas拥有Panel和DrawManifestoGlobal,而Panel本身具有指向Canvas的DrawManifestoGlobal的指针,以便Panel对Canvas所做的任何更改都是可见的。

最佳答案


drawManifesttoGlobal函数中的doSerDe()是一个局部变量,该变量在作用域的末尾到期,但是您要设置一个指向它的指针(Panel::drawManifestoGlobal),并将指针传递到函数外部(通过返回canvas)。因此,您具有访问已破坏对象的值的未定义行为。编译器完全有权为同一对象打印两个不同的值。

如果确实需要一个指针(不需要),则需要动态分配drawManifestoGlobal(最好使用unique_ptr)。

class Panel {
public:
  void setDrawManifestoGlobal(std::unique_ptr<DrawManifestoGlobal> _drawManifestoGlobal);
  std::unique_ptr<DrawManifestoGlobal> drawManifestoGlobal;
};

Canvas SerDe::doSerDe() {
  std::unique_ptr<DrawManifestoGlobal> drawManifestoGlobal(make_unique<DrawManifesttoGlobal>());
  drawManifestoGlobal.value = 99;
  return {std::move(drawManifestoGlobal)};
}

void Panel::setDrawManifestoGlobal(std::unique_ptr<DrawManifestoGlobal> drawManifestoGlobal) {
  drawManifestoGlobal = std::move(_drawManifestoGlobal);
}

事实是您在代码中的任何地方都不需要指针!

07-27 18:17