欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++ vector中push_back()和emplace_back()的区别

程序员文章站 2022-03-21 14:33:48
...

vector的emplace_back()函数是C++11后增加的函数,我们看一看这两个函数的解释:

1. 

push_back

adds an element to the end 
(public member function)

emplace_back

(C++11)

constructs an element in-place at the end  
(public member function)

从上面的解释来看好像是不太好理解,我们看两个函数的具体实现:

std::vector<T,Allocator>::push_back

void push_back( const T& value );

constexpr void push_back( const T& value );

void push_back( T&& value );

constexpr void push_back( T&& value );

std::vector<T,Allocator>::emplace_back

template< class... Args >
void emplace_back( Args&&... args );

template< class... Args >
reference emplace_back( Args&&... args );

template< class... Args >
constexpr reference emplace_back( Args&&... args );

从上面可以看到,push_back()函数的参数是容器对象的左值或者右值,所以只能是已经包装的好的对象才能够当作参数。而对于emplace_back()则是可以传如对象所有需要的参数,然后系统回先根据参数生成一个临时对象,然后将生成的临时对象move到vector中。因此有如下的写法就会出错:

class Person
{
public:
  std::string name_;
  int age_;
  Person(std::string name, int age): name_(name), age_(age) {}
  Person(Person&& rhs) {
    name_ = std::move(rhs.name_);
    age_ = rhs.age_;
    std::cout << "move" << std::endl;
  }
  ~Person() {}
};

int main() {
  std::vector<Person> ps;
  ps.push_back("aaaaa", 10); // error
  ps.push_back("bbbbb", 10); // error
  ps.push_back("ccccc", 10); // error
  ps.emplace_back("aaaaa", 10); // right
  ps.emplace_back("bbbbb", 10); // right
  ps.emplace_back("ccccc", 10); // right

}

特别的如果对象的构建参数只有一个,并且没有explict修饰,那么表现出push_back()和emplace_back()看起来一样的用法,但是对于push_back(parm)来说,他是先生成一个临时变量Object(pram)然后将将这个临时变量copy/move给vector.而对于empalce_back就直接生成一个变量直接到vector,参见[1].

当两个函数都是对象参数的时候, emplace_back(obj) 直接将obj copy/move到一个vector尾端的对象中。而push_back(obj)则是将obj copy/move一个临时对象,这临时对象在move到vector尾部。如下:

#include <iostream>
#include <string>
#include <vector> 
#include <iostream> 
using namespace std;

class Person
{
public:
  std::string name_;
  int age_;
  Person(std::string name, int age): name_(name), age_(age) {}
  Person(Person&& rhs) {
    name_ = std::move(rhs.name_);
    age_ = rhs.age_;
    std::cout << "move" << std::endl;
  }
  ~Person() {}
};

int main() {
  std::vector<Person> ps;

  Person a("aaaaa", 1);
  Person b("bbbbb", 2);
  Person c("ccccc", 3);
  
  ps.emplace_back(std::move(a));
  std::cout<<"========" << std::endl;
  ps.push_back(std::move(b));
  std::vector<Person> psc;

  std::cout << "---------" << std::endl;
  for(Person &p: ps) {
    std::cout<< p.name_ << std::endl;
  }

  for(Person& p: ps) {
    psc.push_back(std::move(p));
  }

  for(Person &p: ps) {
    std::cout<< p.age_ << std::endl;
  }

  return 0;
}

打印结果如下:

move
========
move
move
---------
aaaaa
bbbbb
move
move
move
1
2

[1]

c++11 之emplace_back 与 push_back的区别_学之知之的博客-CSDN博客_emplace_backz​​​​​​​x​​​​​​​u