为什么这种类型的擦除实现(简化的 boost:any)会出现分段错误?
Why does this type erasure implementation (simplified boost:any) gives segmentation fault?
我正在尝试自己实现任意类型的通用容器(类似于 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;
}
输出是我想要的,转换似乎工作正常,但程序总是在最后崩溃。析构函数没有被正确调用或者指针的释放肯定有问题。有人可以给我提示吗?
谢谢
您的 any
类型的隐式定义的复制构造函数只是复制 IValue
指针,因此原始对象和副本都将删除同一个指针。您需要编写一个实际复制存储对象的复制构造函数。
我正在尝试自己实现任意类型的通用容器(类似于 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;
}
输出是我想要的,转换似乎工作正常,但程序总是在最后崩溃。析构函数没有被正确调用或者指针的释放肯定有问题。有人可以给我提示吗?
谢谢
您的 any
类型的隐式定义的复制构造函数只是复制 IValue
指针,因此原始对象和副本都将删除同一个指针。您需要编写一个实际复制存储对象的复制构造函数。