【问题标题】:Is it safe to serialize a raw boost::variant?序列化原始 boost::variant 是否安全?
【发布时间】:2010-11-14 18:08:22
【问题描述】:

boost::variant 声称它是一个值类型。这是否意味着只要简单地写出 boost::variant 的原始表示并稍后将其加载回来是安全的,只要它只包含 POD 类型?假设它将被相同编译器和相同版本的 boost 在相同架构上编译的代码重新加载。

另外,(可能)等效地,可以在共享内存中使用 boost::variant 吗?

【问题讨论】:

  • 吐出原始内存表示,即使它只是 POD 的结构,也是一个糟糕的主意,并且会让您受制于编译器的填充布局、架构细节和字节序。
  • 当时我对共享内存的使用更感兴趣,在这种情况下,布局差异根本不会成为问题。

标签: c++ serialization boost shared-memory boost-variant


【解决方案1】:

尝试只包含 boost/serialization/variant.hpp;它为你工作。

【讨论】:

  • 看到 boost::variant 是为非 POD 类型制作的(否则你可以使用标记的联合),我认为是的,但快速测试会确认。
【解决方案2】:

关于序列化:它应该可以工作,是的。但是为什么不使用boost::variant的访问机制写出变体中包含的实际类型呢?

struct variant_serializer : boost::static_visitor<void> {
    template <typename T>
    typename boost::enable_if< boost::is_pod<T>, void>::type
    operator()( const T & t ) const {
        // ... serialize here, e.g.
        std::cout << t;
    }
};

int main() {

    const boost::variant<int,char,float,double> v( '1' );

    variant_serializer s;
    boost::apply_visitor( s, v );

    return 0;
}

关于共享内存:boost::variant 不执行堆分配,因此您可以像 int 一样将其放入共享内存中,当然前提是同步正确。

不用说,正如你所说,上述仅在变体只能包含 POD 类型时才有效。

【讨论】:

  • 我想避免编写大量样板代码来写出所说的实际类型:)
【解决方案3】:

boost::variant 的内存布局为: { int which; storage_t 存储;}。 storage_t 由实现确定为您的使用所需的最大大小。因此,如果您的 storage_t 为 8 字节或更多(或需要 8 字节对齐),则“which”和“storage”之间可能存在 4 字节填充,具体取决于编译器或编译器选项。因此,正如公认的答案所说,使用访问进行序列化更安全。

【讨论】:

    猜你喜欢
    • 2019-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    相关资源
    最近更新 更多