从函数返回一个包含另一个对象的对象

时间:2018-07-21 00:14:14

标签: c++ function pointers object return

为什么第一次调用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的指针,因此,从Canvas发生的任何更改对Panel都是可见的。

1 个答案:

答案 0 :(得分:1)

  

为什么第一次调用drawManifestoGlobalcout中的值会改变?看来canvas.panel.drawManifestoGlobal被毁了-为什么?

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);
}

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