【问题标题】:static_cast and temporary creation (final edition)static_cast 和临时创作(最终版)
【发布时间】:2011-12-20 20:08:42
【问题描述】:

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

Cast auto_ptr<Base> to auto_ptr<Derived> Steve 回答说 “您的 static_cast 会将 auto_ptr 复制到临时文件中,因此 aS 将被重置,并且当临时文件(在语句末尾)时资源将被销毁。”

我对调用static_cast 时的临时创建过程感兴趣。 我想拥有可以跟踪的代码以查看此效果。 我无法使用static_cast&lt;auto_ptr&lt;Circle&gt;&gt; ...,因为它无法编译,所以我需要编写一些模拟类而不是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时做一个临时对象创建的小模拟?

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

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

【问题讨论】:

  • 您的描述引用了auto_ptr... 在您的示例代码中根本没有使用。你能澄清一下吗?
  • int wmain() 不是标准的 c++ 主函数。
  • @wilhelmtell 我已经编辑了这个问题。如果您对它感兴趣,请重新阅读。
  • "应该调用运算符)。" 哪个运算符?
  • @curiousguy - 已更正!

标签: c++ casting static-cast temporary-objects


【解决方案1】:

在您之前的问题中,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';
}

【讨论】:

  • 耶!!谢谢。史蒂夫,我期待在我以后的问题中寻求您的帮助。谢谢大家,伙计们。这是我需要听到的。
  • @daddyM:.您的代码的问题是您正在制作一个临时 指针,而不是临时 cicle。
  • @MooingDuck 是的。我已经理解了这个事实,并且了解了如何实现非指针转换来调用重载运算符。
【解决方案2】:

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

static_cast<Circle> (c2); 

将从c2“窃取”。

【讨论】:

    【解决方案3】:

    auto_ptr 没问题。正如Steve's answer 解释的那样,该语言足够智能,可以使用普通指针来执行此操作。在基类和派生类之间转换指针可能需要更改指针的值,static_cast 会在需要时执行此操作。

    【讨论】:

    • 好的。我想知道如何模拟创建临时auto_ptr 对象时的情况。在我不起眼的模拟中,operator = 从未调用过。当然,这不是实际问题。这只是理论上的调查。同样,我坚持模拟auto_ptr 临时创建和复制分配运算符调用。如您所见,Circle 类是在auto_ptr 中失去所有权的粗略模拟。
    • 我不明白你在做什么。
    • 请重新阅读问题正文。我添加了一些细节。谢谢!
    【解决方案4】:

    我能想到的最简单的就是这个(如果你改变your original question中的例子):

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

    这个:

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

    创建一个auto_ptr&lt; Circle &gt; 类型的临时对象,它在作用域的末尾破坏auto_ptr&lt; Shape &gt; 类型的对象。

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

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

    【讨论】:

    • 对!这是史蒂夫在我原来的问题的答案中写的。我无法编译上面的代码(使用auto_ptr)。所以,我想模拟这种情况来跟踪这个临时对象的创建。 Circle 类代替了auto_ptr。我想让operator = 在“static_cast”调用期间创建临时文件时运行。你能帮我写正确的模拟代码吗?
    • @DaddyM 我添加了另一个例子说明发生了什么,但没有临时对象。
    • @DaddyM: operator= 在强制转换中复制时不使用,而是使用复制构造函数。所以没有办法做你想做的事,那就是让static_cast 导致对operator= 的调用。
    • @VJovic 谢谢。但这不是我感兴趣的。您展示了a 将如何尝试调用已被b 销毁的存储对象析构函数。我有兴趣模拟这个:static_cast&lt;auto_ptr&lt;Circle&gt;&gt;(aS.get()),但使用另一个 UDF 类(auto_ptr 的原始代码将不起作用)。
    • @SteveJessop 很高兴在这里见到你。你已经理解我了。请告诉如何使用 UDF 类模拟这种情况,该类在复制到临时 static_cast 时模拟“失去所有权”。我很想知道:在 static_cast 中临时创建时跟踪对复制 ctor 的调用。
    猜你喜欢
    • 2011-02-05
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2021-02-28
    • 2014-04-19
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    相关资源
    最近更新 更多