首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ttl::variant,位置新

ttl::variant,位置新
EN

Stack Overflow用户
提问于 2012-05-23 02:22:03
回答 1查看 162关注 0票数 0

我正在使用"Tiny Template Library"中的变量类型。该变体的定义如下:

代码语言:javascript
复制
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_“:

代码语言:javascript
复制
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_回来?

谢谢你,马里奥

EN

回答 1

Stack Overflow用户

发布于 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_来使添加的代码更简单:

代码语言:javascript
复制
pnt_ = &stor_.dummy;

但是,由于您显然只是通过套接字复制了原始内存,因此修复这个variant对象的内部只是冰山一角。您的变量持有的值也可能包含地址,而您无法到达该地址的内部。即使您这样做了,您需要的地址也可能不可用。使用variant很幸运,因为您固定的地址恰好是同一对象中的一个地址,因此很容易计算。但是考虑一下std::string,它从空闲存储中分配内存;通过套接字发送一个内存不会给您提供任何在另一端可用的东西-它甚至可能根本不会给您提供字符数据。相反,您应该使用其他一些技术来序列化和反序列化ttl::variant对象。你可以在Stack Overflow上发布一个问题,询问如何做到这一点。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10707801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档