C++ emplace_back和push_back性能比较

概述

从理论上说,右值引用版的emplace_back要比左值引用版的push_back更快一些,因为前者会调用参数的移动构造函数,而后者会调用参数的拷贝构造函数。熟悉这两种构造函数的读者自然明白移动构造函数不需要重新分配内存空间,所以要比拷贝构造函数耗时更少。

实践

一直只是从理论上知道以上的观点,但是并没有实际验证,刚好一个最近回顾以前的一个项目的时候看到了push_back,所以打算写一段代码验证一下这两种vector插入方法的性能优劣。

要测时间性能,先准备一个打印时间的函数:

//函数中用到的数据类型和库函数包含在头文件
//打印微秒级当前时间
static int64_t TimeStampMS(){
    struct timeval tv;
    ::gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

这段测试代码的设计思路:从文件中按行读取string类型数据插入到vector中,然后分别打印两种方法(emplace_back和push_back)的耗时时间,对比看哪一种耗时更少。

全部代码:

#include 
#include 
#include 
#include 
#include  //std::move
#include 

struct WordInfo{
  int64_t id;
  std::string word; 
};

std::vector<WordInfo> dict;
//dict_data文件包含100 000行数据
std::string InputPath = "./dict_data";

static int64_t TimeStampMS(){
  struct timeval tv;
  ::gettimeofday(&tv, NULL);
  return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

//创建一个临时对象初始化后插入到vector中
void BuildWord(const std::string& word){
  WordInfo word_info; 
  word_info.id = dict.size();
  word_info.word = word;
  //dict.push_back(word_info); //测试 push_back
  dict.emplace_back(std::move(word_info)); //测试 emplace_back
}

void BuildDict(const std::string& input_path){
  std::ifstream file(input_path.data());
  if(!file.is_open()){
    std::cout << "Open file faild!!!" << std::endl;
    exit(EXIT_FAILURE);
  }
  std::string line;
  int64_t begin = TimeStampMS();
  while(std::getline(file, line)){
    BuildWord(line);   
  }
  std::cout << "time: " << TimeStampMS() - begin << "ms" << std::endl;
  file.close();
  std::cout << "Building a successful." << std::endl;
}

int main() {
  BuildDict("./dict_data");
  return 0;
}

push_back耗时结果:

C++ emplace_back和push_back性能比较_第1张图片

emplace_back耗时结果:

C++ emplace_back和push_back性能比较_第2张图片

经比较可得知,使用emplace_back插入临时对象要比使用push_back耗时更少。

总结

开发中需要向vector插入临时对象时,如果编译器支持C++11,那么最好用emplace_back替代push_back。

你可能感兴趣的:(C/C++语言,STL)