为什么这种类型的擦除实现(简化的boost:any)会给出分段错误?

时间:2017-11-06 22:28:20

标签: c++ boost-any boost-type-erasure

我正在尝试自己实现任意类型的通用容器(类似于boost:any)只是为了了解这个成语,我试图理解为什么我的代码会产生分段错误。

class IValue
{
public:
    IValue() = default;
    virtual ~IValue() = default;
};

template<typename T>
class Value : public IValue
{
public:
    Value(T value) : val(value){}

    virtual ~Value() override
    {
    }

    T get()
    {
        return val;
    }
private:
    T val;
};

class any
{

public:
    template<typename U>
    any(U element)
    {
        elem = new Value<U>(element);
    }

    ~any()
    {
        delete elem;
    }

    IValue* get_type_erased_value()
    {
        return elem;
    }


private:
    IValue* elem;
};

template<typename T>
T any_cast(any a)
{
    Value<T>* stored_element = dynamic_cast<Value<T>*>(a.get_type_erased_value());

    if(stored_element)
    {
        return stored_element->get();
    }
    else
    {
        cout << "Any cast failed. Could not cast down to required type\n";
        return T();
    }

}

struct foo
{
    int a;
    float b;
    char c;
};

ostream& operator<<(ostream& stream, foo& a)
{
    stream << '{' << a.a << ',' << a.b << ',' << a.c << '}' << '\n';
    return stream;
}

int main()
{
    any a = string("Any string value");

    any b = int(17);

    any c = foo({27,3.5,'g'});

    string s = any_cast<string>(a);
    int i = any_cast<int>(b);
    foo f = any_cast<foo>(c);

    cout << "Any string contained: " << s << '\n';
    cout << "Any int contained: " << i << '\n';
    cout << "Any struct foo contained: " << f << '\n';

    return 0;
}

输出是我想要的,并且转换似乎正常工作,但程序总是在最后崩溃。析构函数未被正确调用或指针的重新分配必定存在问题。有人可以给我一个暗示吗?

由于

1 个答案:

答案 0 :(得分:1)

any类型的隐式定义的复制构造函数只复制IValue指针,因此原始对象和副本都将删除相同的指针。您需要编写一个实际复制存储对象的复制构造函数。