static_cast 和临时创建(最终版)

发布于 2024-12-22 01:42:15 字数 1742 浏览 1 评论 0 原文

先决条件: 要理解这个问题,请首先阅读以下问题及其答案: 转换 auto_ptr到 auto_ptr

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

我对调用 static_cast 时临时创建的过程感兴趣。 我想要有可以跟踪的代码,以便看到这种效果。 我无法使用 static_cast> ...因为无法编译,所以我需要编写一些模拟类来代替auto_ptr并观察临时创建的过程。

我还了解到临时创建与复制构造函数调用密切相关。 auto_ptr 的所有权丢失是通过复制分配来模拟的,将源的 _radius 字段设置为负值(我需要 auto_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 时对临时对象创建进行小模拟?

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

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

Prerequisities:
To understand this question, please, read the following question and its answer at first:
Cast auto_ptr<Base> to auto_ptr<Derived>

At
Cast auto_ptr<Base> to auto_ptr<Derived> Steve answered that "Your static_cast would copy the auto_ptr to a temporary, and so aS would be reset and the resource would be destroyed when the temporary is (at the end of the statement)."

I'm interested in the process of temporary creation while static_cast is called.
I would like to have the code that I can trace in order to see this effect.
I cannot use static_cast<auto_ptr<Circle>> ... because it cannot be compiled, so I need to write some simulation class instead of auto_ptr and watch the process of temporary creation.

I also understand that temporary creation is closely connected with copy constructor call.
auto_ptr's ownership loosing is simulated with copy assignment that set the _radius field of source to negative value (I need the simple logical model of auto_ptr).

So, I suggest the following Circle class:

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

Ok. Here we can see that "ownership transferring" is taking place in c2 = c3.
BUT I cannot achieve temporary creation in static_cast.

The question is: how to make a small simulation of temporary object creation while static_cast?

I believe Steve that temporary object is created while casting. The only thing I want is to write an example that shows temporary creation. This target has academic reasons.

Can someone clarify how to achieve the effect described in Steve's answer that he posted at the referred topic?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

┾廆蒐ゝ 2024-12-29 01:42:15

在上一个问题中,auto_ptr 是拥有所有权的类,并在复制时将源的指针重置为 null。

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

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

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

In your previous question, auto_ptr is the class that has ownership, and resets the source's pointer to null when it is copied.

Now, Circle is a class that simulates ownership, by resetting its radius to -1 when it is copied. So it's like an auto_ptr in that way, but not in any other way.

So, to observe loss of simulated ownership you need to copy a Circle, which is what you do with copy assignment in the line c2 = c3. Casting a Circle* doesn't copy the object, just the pointer, but casting a Circle does copy the object:

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

Output is -1.

Or if you specifically want to see it with a cast to a derived class:

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';
}
宛菡 2024-12-29 01:42:15

好的。这里我们可以看到,c2 = c3 中正在发生“所有权转移”。但我无法在 static_cast 中实现临时创建。

static_cast<Circle> (c2); 

将从c2“窃取”。

Ok. Here we can see that "ownership transferring" is taking place in c2 = c3. BUT I cannot achieve temporary creation in static_cast.

static_cast<Circle> (c2); 

will "steal" from c2.

_畞蕅 2024-12-29 01:42:15

您可以使用auto_ptr。正如 Steve 的回答所解释的,该语言足够智能,可以使用普通指针来完成此操作。在基类和派生类之间转换指针可能需要更改指针的值,而 static_cast 将在需要时执行此操作。

You're fine with the auto_ptr. As Steve's answer explains, the language is smart enough to do this with ordinary pointers. Casting a pointer between base and derived classes can require changing the value of the pointer, and a static_cast will do that when needed.

各空 2024-12-29 01:42:15

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

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

这:

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

创建一个临时的类型 auto_ptr< Circle > ,它会破坏 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;
}

The simplest I could think of is this (if you change the example in your original question) :

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

This :

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

creates a temporary of type auto_ptr< Circle >, which destructs the object of type auto_ptr< Shape > at the end of the scope.

Here is an example (I hope it is clear enough) :

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文