4

先决条件: 要理解这个问题,请先阅读以下问题及其答案: Cast auto_ptr<Base> to auto_ptr<Derived>

将 auto_ptr<Base> 转换为 auto_ptr<Derived> 时,Steve 回答说:“您的 static_cast 会将 auto_ptr 复制到临时对象,因此 aS 将被重置,并且当临时对象存在时(在语句末尾),资源将被销毁。 "

我对static_cast调用时的临时创建过程感兴趣。我想拥有可以跟踪的代码以查看此效果。我不能使用static_cast<auto_ptr<Circle>> ...,因为它无法编译,所以我需要编写一些模拟类而不是auto_ptr观看临时创建的过程。

我也明白临时创建与复制构造函数调用密切相关。 的所有权丢失是通过将源字段设置为负值auto_ptr的复制分配来模拟的(我需要 的简单逻辑模型)。_radiusauto_ptr

所以,我建议以下Circle课程:

#include <iostream>

class Shape {};

class Circle: public Shape {
  double _radius;
public:
  explicit Circle(double radius = .5): _radius(radius) {}
  Circle &operator =(Circle &circle) {
    _radius = circle._radius;
    circle._radius = -1.;
    return *this;
  }
  Circle(Circle &circle) { *this = circle; }
  double GetRadius() { return _radius; }
};

int wmain() {
  using namespace std;

  Circle c1(100), c2(200), c3(300);
  c2 = c3;

  Shape *s1, s2;
  s1 = &c1;
  wcout << static_cast<Circle *>(s1)->GetRadius() << endl;

  return 0;
}

行。在这里我们可以看到“所有权转移”正在发生c2 = c3。但我无法在static_cast.

问题是:如何对临时对象的创建进行小模拟static_cast

我相信史蒂夫是在铸造时创建的临时对象。我唯一想要的是编写一个显示临时创建的示例。这个目标有学术原因。

有人可以澄清如何达到史蒂夫在提到的主题上发布的答案中描述的效果吗?

4

4 回答 4

3

在您之前的问题中,auto_ptr是拥有所有权的类,并在复制源的指针时将其重置为 null。

现在,Circle是一个模拟所有权的类,通过在复制时将其半径重置为 -1。因此,它就像auto_ptr以那种方式,但不是以任何其他方式。

因此,要观察模拟所有权的丢失,您需要复制 a Circle,这就是您对行中的复制分配所做的事情c2 = c3。强制转换a不会复制Circle*对象,只会复制指针,但强制转换 aCircle会复制对象:

int main() {
    Circle c1(100);
    static_cast<Circle>(c1);
    std::cout << c1.GetRadius() << '\n';
}

输出为-1。

或者,如果您特别想通过转换为派生类来查看它:

struct SpecialCircle: Circle {
    SpecialCircle(Circle &circle) : Circle(circle) {}
    explicit SpecialCircle(double radius = .5): Circle(radius) {}
};

int main() {
    SpecialCircle s1(100);
    Circle &c1 = s1;
    static_cast<SpecialCircle>(c1);
    std::cout << c1.GetRadius() << '\n';
}
于 2011-12-21T10:01:03.270 回答
1

行。在这里我们可以看到“所有权转移”发生在 c2 = c3 中。但我无法在static_cast.

static_cast<Circle> (c2); 

将从中“窃取” c2

于 2011-12-21T11:53:29.053 回答
0

你没问题auto_ptr。正如史蒂夫的回答所解释的,这种语言足够聪明,可以用普通的指针来做到这一点。在基类和派生类之间转换指针可能需要更改指针的值,并且 astatic_cast会在需要时执行此操作。

于 2011-12-20T20:19:23.803 回答
0

我能想到的最简单的是(如果您更改原始问题中的示例):

wcout << aS->GetName() << L'\t' << static_cast<auto_ptr<Circle>>(aS.get())->GetRadius() << endl;

这 :

static_cast<auto_ptr<Circle>>(aS.get())

创建一个临时的 type ,它在作用域的末尾auto_ptr< Circle >破坏 type 的对象。auto_ptr< Shape >

这是一个例子(我希望它足够清楚):

#include <iostream>
#include <memory>

struct B
{
    ~B()
    {
        std::cout<<"~B"<<std::endl;
    }
    void foo()
    {
        std::cout<<"foo"<<std::endl;
    }
};
struct A : B
{
    ~A()
    {
        std::cout<<"~A"<<std::endl;
    }
    void bar()
    {
        std::cout<<"boom"<<std::endl;
    }
};

int main() {
    std::auto_ptr< A > a( new A );
    {
        std::auto_ptr< B > b( a.get() );
        b->foo();
    }

    std::cout<<"prepare for the crash"<<std::endl;
}
于 2011-12-20T20:55:54.840 回答