在std::vector中有效的push_back

efficient push_back in std::vector

本文关键字:push back std vector 有效      更新时间:2023-10-16

在下面的代码中,为执行push_back()创建了3个d1和d2对象。一次是在创建的时候,一次是在调用v.p ash_back()的时候,还有一次是在将它实际复制到向量{我不确定}的时候。

在c++ 03中,如果不使用std::vector,那么避免这种情况的最佳选择是什么?
#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct Details
{
    string fname;
    string lname;
    string address;
    int age;
};
int main(int argc, char **argv)
{
    vector<Details> v;
    Details d1;
    d1.fname = "vivek";
    d1.lname = "kumar";
    d1.address = "New Delhi";
    d1.age = 25;
    v.push_back(d1);
    Details d2;
    d2.fname = "some name";
    d2.lname = "some lastname";
    d2.address = "some address";
    d2.age = 25;
    v.push_back(d2);
    return 0;
}

调用std::vector::push_back()本身并不创建副本,因为传递了const引用。它只创建成为vector元素的副本。这个拷贝是std::vector的语义所要求的。

您还可以在复制成本相对较低的时候将Details替换为push_back():

Details d1; // Now the 3 strings of d1 are still small
v.push_back(d1); // essentially copies 3 empty strings and an int.
v.back().fname = "vivek";
v.back().lname = "kumar";
v.back().address = "New Delhi";
v.back().age = 25;

如果您真的确定性能在这里是最重要的,那么您将需要/实现引用语义。

  • 在c++ 11中,你有移动语义,所以你会为Details结构实现一个移动构造函数,所以我通常强烈建议使用
  • 因为你使用的是c++ 03,你可以使用boost::shared_ptr来包装你的细节结构,像这样:vector<boost::shared_ptr<Details> >。由于您使用的是c++ 03,请注意>之间的空格字符。
  • 通常我会推荐unique_ptr而不是shared_ptr,但unique_ptr仅在c++ 11中可用,其中移动语义替代在大多数情况下更好。
  • 我不推荐原始指针的原因是因为你需要手动管理它们的内存,这是一个禁忌。

至于你的例子,请注意,在c++ 03中,push_back接受const引用,因此只涉及到结构的一个副本。使用我上面建议的任何方法仍然会做一个副本,但是副本的大小将保持在检查中,并且不会随着结构的大小而缩放,这可能正是您在处理大数据时所希望的。