使用 Used-defined 转换运算符时出现分段错误

Segmentation fault when using Used-defined conversion operator

我已经实现了下面的一段代码

#include <iostream>
#include <memory>

class A
{
    public:
        int a;

        virtual ~A()
        {
        }
};

class B : public A
{
    public:
        int b;

        virtual ~B()
        {
        }
};

class E : public B
{
    public:
        ~E()
        {
        }
};

class D
{
public:
    operator std::shared_ptr<A>()
    {
        std::shared_ptr<A> pa = std::make_shared<A>();
        pa->a = this->y;
        return pa;
    }

    operator std::shared_ptr<B>()
    {
        std::shared_ptr<A> pb = std::make_shared<B>();

        pb = *this;
        (std::static_pointer_cast<B>(pb))->b = this->x;
        return std::static_pointer_cast<B>(pb);
    }

    virtual ~D()
    {
    }

    int x;
    int y;
};

int main()
{
    D d;
    d.x = 6;
    d.y = 7;
    std::shared_ptr<E> pE = std::make_shared<E>();
    std::shared_ptr<A> pa = pE;

    std::shared_ptr<B> pB = std::dynamic_pointer_cast<B>(pa);
    pB = d;
    std::cout << "a " << pB->a << "b " << pB->b << std::endl;
    return 0;
}

我尝试做的是将 class Dd 的实例转换为从 [= 派生的共享指针 B 的实例33=] A.

B继承classAE继承classB

当程序终止时,程序在classA的析构函数中崩溃。

我使用了 GDB,发现 this 是 NULL。

有人知道为什么会这样吗?

D::operator std::shared_ptr<B>()内部,std::static_pointer_cast<B>(pb)的使用是未定义的行为,因为pb没有指向[=的实例14=],所以将 A 指针转换为 B 指针并访问 B 的成员是非法的。 pb 指向 std::make_shared<A>()D::operator std::shared_ptr<A>() 中创建的 A 实例。在语句 pb = *this; 中,您正在丢弃您创建的 B 对象并获得 *this returns.

A 对象的所有权

因此,在 main() 内部,pB 最终指向无效的 B 对象,并在 main() 退出时尝试破坏该对象,这就是为什么你最终导致 A 析构函数崩溃。

如果您在 D::operator std::shared_ptr<B>() 中使用 dynamic_pointer_cast 而不是 static_pointer_cast,您最终会得到一个 NULL 指针,并且在访问 [时可能会在 D::operator std::shared_ptr<B>() 中崩溃=35=],而不是在 main().

中崩溃

您需要修复 operator std::shared_ptr<B>() 以在 B 的有效实例上运行,而不是在 A 的实例上运行。例如:

operator std::shared_ptr<B>()
{
    std::shared_ptr<B> pb = std::make_shared<B>();
    std::shared_ptr<A> pa = *this;

    *static_pointer_cast<A>(pb) = *pa; // <-- copy pa->a to pb->a ...
    // or: simply do this instead:
    // pb->a = pa->a;

    pb->b = this->x;
    return pb;
}