我正在使用"Tiny Template Library"中的变量类型。该变体的定义如下:
template< TTL_TPARAMS_DEF(TTL_MAX_TYPELIST_PARAMS, empty_type) >
struct variant
{
typedef variant this_t;
typedef meta::typelist< TTL_ARGS(TTL_MAX_TYPELIST_PARAMS) > list;
...
template< typename T >
variant( const T& r ) : which_(0), pnt_(0)
{
typedef meta::find_equivalent_type<const T&, list> found;
pnt_ = new(stor_.buf_) ttl::data_holder<typename found::type>(r);
which_ = found::index;
}
...
private:
template<int N>
struct storage
{
union
{
ttl::data_holder_base dummy; //hope to satisfy alignment settings
char buf_[N];
};
};
int which_;
ttl::data_holder_base* pnt_;
storage< sizeof(ttl::data_holder<typename list::largest_type>) > stor_;
....
};
struct data_holder_base {};
template< typename T >
struct data_holder : data_holder_base
{
...
typedef const T& param_type;
T d;
...
data_holder( param_type d_ ) : d(d_) {}
...
};当我通过网络发送此类型的对象并使用"memcpy“”重建“它时,很明显指针"pnt_”将指向涅盘。由于我知道存储的类型,所以我尝试使用强制转换重新构建指针"pnt_“:
template<typename T>
inline void rebuild()
{
pnt_ = reinterpret_cast<ttl::data_holder<T>*>(stor_.buf_);
}对于这种情况,我检查了这个例子,它是有效的。但我不知道放置新对象(pnt_ = new(stor_.buf_) ...)是如何将对象放置到stor_.buf_中的。是否需要存储像std::distance(&stor_.buf_[0], pnt_)这样的内容才能找到对象?
还是有别的方法能让pnt_回来?
谢谢你,马里奥
发布于 2012-05-23 02:54:13
Placement new将新对象放在stor_.buf_中,因为这就是placement new的工作方式。您为new提供了您希望它使用的内存地址,它将在该位置构造对象。它返回完全相同的地址,所以存储在pnt_中的地址是stor_.buf_的地址,但是它的类型是构造的对象ttl::data_holder<found::type>,而不是char*。由于地址相同,您提到的std::distance值将始终为零(假设调用会编译,但不会编译,因为参数类型不同)。
stor_.buf_的地址也将始终等于stor_.dummy的地址。您可以通过像这样分配pnt_来使添加的代码更简单:
pnt_ = &stor_.dummy;但是,由于您显然只是通过套接字复制了原始内存,因此修复这个variant对象的内部只是冰山一角。您的变量持有的值也可能包含地址,而您无法到达该地址的内部。即使您这样做了,您需要的地址也可能不可用。使用variant很幸运,因为您固定的地址恰好是同一对象中的一个地址,因此很容易计算。但是考虑一下std::string,它从空闲存储中分配内存;通过套接字发送一个内存不会给您提供任何在另一端可用的东西-它甚至可能根本不会给您提供字符数据。相反,您应该使用其他一些技术来序列化和反序列化ttl::variant对象。你可以在Stack Overflow上发布一个问题,询问如何做到这一点。
https://stackoverflow.com/questions/10707801
复制相似问题