【问题标题】:How move semantic works in vector relocation?向量重定位中的移动语义如何工作?
【发布时间】:2015-08-20 03:28:35
【问题描述】:

据我了解,当向量增加容量时,它会分配新内存,将所有内容复制(移动?)到新数组,然后销毁旧数组:

vector<int> v;
v.emplace_back(1);
v.emplace_back(2); cout<<&v[0]<<endl; // outputs 0x4b16d0
v.emplace_back(3); cout<<&v[0]<<endl; // outputs 0x4b16f0

         +-----+  
0x4b16d0 | 1 2 |  
         +-----+  

         +---------+  
0x4b16f0 | 1 2 3   |  
         +---------+  

在上面的例子中,1 和 2 move 如何从 0x4b16d0 到 0x4b16f0?


用用户定义的类更新

struct foo {
    foo() {}
    foo(const foo &) { cout << "copy\n"; }
    foo(foo &&) noexcept { cout << "move\n"; }
};

int main() {
    vector<foo> v;
    cout<<"1st emplace_back() \n"; v.emplace_back(); cout<<" addr of 1st element: "<<&v[0]<<endl;
    cout<<"2nd emplace_back() \n"; v.emplace_back(); cout<<" addr of 1st element: "<<&v[0]<<endl;
}

$ g++ -std=c++11 -g a.cpp; ./a.exe
1st emplace_back()
 addr of 1st element: 0x6f16d1
2nd emplace_back()
move
 addr of 1st element: 0x6f16f1

我的问题是,即使调用了move ctor,它仍然会将数据从一个地方复制到另一个地方,对吗?

如果是这样,这是否意味着当向量使用移动语义增加其容量时它根本不会提高性能?

【问题讨论】:

  • 它使用您问题中描述的方法。它会复制它们。
  • 具有用户定义的移动构造器 + 调试器 + 断点 + 视图调用堆栈的非平凡类可能会让您了解您的实现如何做到这一点。还是您的问题是专门针对int 的?
  • @Deqing 你知道这两个都应该使用&amp;v[0],对吧?
  • 提示:每次调用v.emplace_back() 后输出v.capacity()。现在,你为什么认为第一个元素的地址在改变?
  • 可能还需要记住:如果对象具有无抛出移动构造函数,向量只会移动您的对象。默认情况下,它最终会以这种方式声明(很可能)。如果移动构造函数可能抛出,那么向量将使用复制构造函数。它基于这个标准实用程序:en.cppreference.com/w/cpp/utility/move_if_noexcept

标签: c++ c++11 vector move-semantics


【解决方案1】:

您的向量是 vector&lt;int&gt; 。移动int 与复制它是一样的,所以这里没有“性能提升”。

如果您有vector&lt;std::string&gt;,那么您会注意到不同;大字符串将从旧内存位置移动到新内存位置。这将比在新位置复制构造新字符串并破坏旧字符串更快。

(正如 Chris Beck 所指出的,只有当它们的移动构造函数不能抛出时,对象才会被移动,但我相信 std::string 就是这种情况)。

我不确定您要在 foo 示例中测试什么,因为您的 foo 实际上不包含任何数据。

【讨论】:

    猜你喜欢
    • 2019-08-04
    • 1970-01-01
    • 2021-07-24
    • 2023-03-29
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多