【问题标题】:std::vector: contiguous data and copy/movestd::vector:连续数据和复制/移动
【发布时间】:2014-08-12 07:56:31
【问题描述】:

我对以下代码有两个问题:1) faces 的元素是否连续? 2) std::vector 插入时是否复制或移动Face f

#include <vector>    
int main()
{
    struct Face {};
    std::vector<Face> faces;

    for (int i=0; i<10; ++i)
    {
        Face f;

        faces.push_back (f);
    }

    return 0;
}

【问题讨论】:

  • 如果您担心它会复制或移动它(在这种特殊情况下是移动)- 为什么不使用.emplace
  • @BenjaminGruenbaum:push_backemplace_back 都将使用复制构造函数在 std::vector 中创建对象(在本例中)。
  • @nosid 我的意思是 - 与其在循环之外创建它,不如将它放置在循环中。我很想听听为什么它不能利用移动语义。我的印象是 gcc 和 clang 会很容易做到这一点(假设一个不是“空”的结构)
  • @BenjaminGruenbaum:我不明白你所说的在循环之外在循环中是什么意思。不管怎样,f 是一个左值引用,编译器不能将移动构造函数用于左值引用——push_backemplace_back 都不能。此规则的唯一例外是 return 语句。
  • @chris 不是。它们本来应该是连续的,当发现 C++98 标准没有明确说明时,他们在 C++03 中添加了一段以确保它是连续的。我认为从来没有一个不连续的 std::vector 实现。

标签: c++ c++11 stdvector contiguous


【解决方案1】:

根据标准§ 23.3.6.1 类模板向量概述[vector.overview]:

vector 的元素连续存储,这意味着如果vvector&lt;T, Allocator&gt;,其中Tbool 以外的其他类型,那么它服从身份&amp;v[n] == &amp;v[0] + n for all 0 &lt;= n &lt; v.size()

就您在先前 C++11 编译器中的第二个问题而言,push_back 会复制您推回的对象。

在 C++11 之后,它取决于 push_back 有两个重载,一个采用 lvalue 引用,另一个采用 rvalue 引用。

在您的情况下,它将被复制,因为您将对象作为lvalue 传递。为了确保对象的移动,您可以使用std::move()

faces.push_back(std::move(f));

【讨论】:

  • 你确定这里是它将被复制而不是它可能被复制?在这种特殊情况下执行移动的编译器是否违反规范?
  • @BenjaminGruenbaum 如果您指的是复制省略,如果我没记错的话,这不是可以应用的情况之一。 coliru.stacked-crooked.com/a/ca6136f941af40eb
  • @BenjaminGruenbaum:不能移动,因为它既没有转换为右值引用,也没有作为左值返回,也没有作为未命名的未绑定对象开始。也不能有复制省略,40two 是对的。
  • 嗯,“好像”规则是否已从最新版本的标准中删除?
  • @NicolaMusatti 不,“好像”规则仍然有效(请参阅第 1.9/5 节程序执行 [intro.execution])。重载解决规则是罪魁祸首:)。
猜你喜欢
  • 2015-09-10
  • 2014-03-27
  • 2013-10-17
  • 1970-01-01
  • 2015-04-01
  • 2021-12-12
  • 2011-09-21
  • 2018-02-02
  • 1970-01-01
相关资源
最近更新 更多