【问题标题】:c++ std::pair, std::vector & memcopyc++ std::pair, std::vector & memcpy
【发布时间】:2011-01-01 20:16:56
【问题描述】:

从 a 的第一个元素的内存地址中复制 myvect.size()*sizeof(foo) 个字节是否安全

std::vector<std::pair<T1, T2> > myvect

放入数组中

struct foo{
    T1 first;
    T2 second;
}

如果数组分配的元素数量与向量的大小相同?

谢谢

【问题讨论】:

  • std::pair 是一个结构,标准说编译器确定布局,但必须保持顺序,所以在 std::pair 的实例中,您的编译器可能决定在每个字符之后放置 3 字节填充以实现最佳对齐,所以不,你不能假设连续的内存布局 - 故事结束。

标签: c++ vector memcpy std-pair


【解决方案1】:

不,包含T1T2 的类不能保证与std::pair&lt;T1, T2&gt; 相同的布局或对齐方式,至少在C++98 中是这样(因为std::pair 不是POD 类型)。在 C++0x 中情况可能会有所不同。

【讨论】:

  • @Chris: 标准布局,但是标准布局类对于复制来说不是必要安全的,它只是意味着(实际上)编译器没有插入任何令人讨厌的惊喜。 RAII 类包含指向堆分配对象的指针,它在销毁时释放并在分配时克隆,是标准布局但不是 POD,可能不应该使用 memcpy 复制。
  • @Michael:仅当 struct foo 是 POD 类型时。 :-P(对于这个问题,这意味着T1T2 也是。)
  • 这就是为什么 std::copy 不仅仅是纯粹主义者感兴趣的原因 - 它复制非 POD 数据。
  • @Chris:是的——我忽略了那个细节(相反,我认为它们是 POD 类型——一个危险的假设)。但是,std::copy() 即使不是 POD 也可以工作(只要类型支持赋值)。所以这让我的“纯粹主义”破解错了——应该简单地使用它。如果类型是 POD,优化会导致编译器吐出 memcpy() 等效代码 - 我将不得不查看一些 asm 输出,看看这是否真的发生在实践中。在任何情况下,输出都可能足够好,除非它不是(挥手怎么样?)。
  • 实际上,一些编译器为std::copy() 创建的代码比std::memcpy()更好 - std::copy() 的特化很容易从类型对齐限制中受益。例如。 std::copy&lt;double*&gt; 可以使用 64 位对齐的读/写,而无需事先检查。
【解决方案2】:

你没问的问题的答案大概是std::transform

struct pairToFoo {
    // optionally this can be a function template.
    // template<typename T1, typename T2>
    foo operator()(const std::pair<T1,T2> &p) const {
        foo f = {p.first, p.second};
        return f;
    }
};

std::transform(myvect.begin(), myvect.end(), myarray, pairToFoo());

std::copy,但给 foo 一个 operator= 以一对作为参数。不过,这假设您可以重写 foo:

struct foo {
    T1 first;
    T2 second;
    foo &operator=(const std::pair<T1,T2> &p) {
        first = p.first;
        second = p.second;
        return *this;
    }
};

std::copy(myvect.begin(), myvect.end(), myarray);

【讨论】:

  • std::transform() 是我不记得的东西。曾经。也许现在我已经公开说过了,它有时会突然出现在我的脑海中。
  • std::transform 是你得到的,而不是 map 和 zipWith。所以也许如果你每次忘记transform,你在Haskell中重新编写相关函数,你就会记住它。如果只是为了避免编写 Haskell。
【解决方案3】:

一般来说,不会。在某些平台/编译器/STL 实现上可能是这样,但无论如何都不要这样做。您将依赖 pair 和 vector 的实现细节。

我自己犯了依赖 vector 作为连续数组的罪过。为此,我深深忏悔。但是这对...只是说不。

【讨论】:

  • 其实vector保证是一个连续的数组。
  • std::vector&lt;T&gt; 是连续的(我认为未来的 C++ 版本会这样指定),并且&amp;vec[0] 应该可以用作大小为vec.size() 的数组,这一点已被广泛接受。但是,对 std::pair 这样的非 POD 类型执行 memcpy 是有风险的。
  • 原谅你,即使在 C++03 中... std::vector 需要使用连续存储。
  • @Seva:来自 C++03 草案标准 23.2.5,“向量的元素是连续存储的,这意味着如果 v 是向量 其中 T 是某种类型除了 bool 之外,对于所有 0
  • @Seva: C++03, 23.2.4.1: 向量的元素是连续存储的,这意味着如果 v 是向量 其中 T 是 bool 以外的某种类型,那么它对于所有 0
猜你喜欢
  • 2013-08-18
  • 1970-01-01
  • 2011-10-29
  • 2013-03-08
  • 1970-01-01
  • 2021-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多