我希望看到push_back和emplace_back之间的区别,因为在我看过推荐的几个地方,现在最好使用emplace_back作为“它可以做所有push_back可以做的事情,也可以做更多”,所以我希望ti会更有效率。但令我惊讶的是
#include <iostream>
#include <vector>
class A
{
public:
A() {std::cout << "A const" << std::endl;}
~A() {std::cout << "A dest" << std::endl;}
A(const A& a) {std::cout << "A copy const" << std::endl;}
A(A&& a) {std::cout << "A move const" << std::endl;}
A& operator=(const A& a) {std::cout << "A copy operator=" << std::endl; return *this; }
A& operator=(A&& a) {std::cout << "A move operator=" << std::endl; return *this; }
};
int main () {
std::vector<A> va;
std::cout <<"push:" << std::endl;
va.push_back(A());
std::cout <<std::endl<< "emplace:" << std::endl;
va.emplace_back(A());
std::cout <<std::endl<< "end:" << std::endl;
return 0;
}输出是
push:
A const
A move const
A dest
emplace:
A const
A move const
A copy const
A dest
A dest
end:
A dest
A destemplace_back调用move构造函数,然后在push_back只调用一个move时复制构造函数。我检查了g++ (Ubuntu7.4.0-1ubuntu1~16.04~ppa1 1) 7.4.0和在线C++外壳。我是不是遗漏了什么?
发布于 2020-05-25 21:41:28
push_back 效率不高,您所观察到的结果是向量自身调整大小的结果。
当您在emplace之后调用push_back时,向量必须自行调整大小,以便为第二个元素腾出空间。这意味着它必须移动最初位于向量内的A,从而使emplace看起来更加复杂。
如果事先在向量中预留了足够的空间,这种情况就不会发生。请注意在创建va.reserve(2)之后对va的调用:
#include <iostream>
#include <vector>
class A
{
public:
A() {std::cout << "A const" << std::endl;}
~A() {std::cout << "A dest" << std::endl;}
A(const A& a) {std::cout << "A copy const" << std::endl;}
A(A&& a) {std::cout << "A move const" << std::endl;}
A& operator=(const A& a) {std::cout << "A copy operator=" << std::endl; return *this; }
A& operator=(A&& a) {std::cout << "A move operator=" << std::endl; return *this; }
};
int main () {
std::vector<A> va;
// Now there's enough room for two elements
va.reserve(2);
std::cout <<"push:" << std::endl;
va.push_back(A());
std::cout <<std::endl<< "emplace:" << std::endl;
va.emplace_back(A());
std::cout <<std::endl<< "end:" << std::endl;
return 0;
}相应的输出是:
push:
A const
A move const
A dest
emplace:
A const
A move const
A dest
end:
A dest
A dest我们能让事情变得更有效率吗?是的!emplace_back接受您提供的任何参数,并将它们转发给A的构造函数。因为A有一个不带参数的构造函数,所以也可以使用不带参数的emplace_back!换句话说,我们改变了。
va.emplace_back(A());至
va.emplace_back(); // No arguments necessary since A is default-constructed这将导致不复制,也不会移动:
push:
A const
A move const
A dest
emplace:
A const
end:
A dest
A dest关于向量调整大小的注意事项:需要注意的是,std::vector的实现是明智的。如果A是一种微不足道的可复制类型,那么std::vector就可以在不使用类似于realloc的系统功能的情况下调整相应的大小。但是,由于A的构造函数和破坏包含代码,所以不能在这里使用realloc。
https://stackoverflow.com/questions/62011157
复制相似问题