emplace_back、push_back杂谈
emplace_back
相当于是直接初始化,根据函数重载找最佳匹配的构造函数。若emplace
的是一个完整的对象,则根据函数匹配规则,会自动调用拷贝构造函数。
push_back
相当于是拷贝初始化(但是编译器不会进行优化),若push
的对象不是完整的对象,则会进行类型转换,转换之后进行添加,添加时会调用拷贝构造函数。
若push_back
有右值引用的版本,添加的对象又是一个右值,此时会调用右值版本的移动构造。速度也会很快。
性能差别
- 当插入的都是临时对象时,性能没有差别。
- 如果有移动构造函数,两者都会先调用构造函数,后调用移动构造函数,性能没有差别。
- 没有,两者都会先调用构造函数,后调用拷贝构造函数,性能没有差别。
1 |
|
运行结果
1 |
|
当插入的时完整的对象时,性能没有差距。
- 因为
push_back()
是直接调用拷贝构造函数,emplace_back
是按照函数匹配规则调用拷贝构造函数,两者性能相同。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21int main()
{
std::vector<President> elections;
President temp("Franklin Delano Roosevelt", "the USA", 1936);
std::cout << "emplace_back:\n";
elections.emplace_back(temp);
std::vector<President> reElections;
std::cout << "\npush_back:\n";
reElections.push_back(temp);
std::cout << "\nContents:\n";
for (President const& president: elections) {
std::cout << president.name << " was elected president of "
<< president.country << " in " << president.year << ".\n";
}
for (President const& president: reElections) {
std::cout << president.name << " was re-elected president of "
<< president.country << " in " << president.year << ".\n";
}
}1
2
3
4
5
6
7
8
9
10I am being constructed.
emplace_back:
I am being copy constructed.
push_back:
I am being copy constructed.
Contents:
Franklin Delano Roosevelt was elected president of the USA in 1936.
Franklin Delano Roosevelt was re-elected president of the USA in 1936.- 因为
当
push_back
一个临时对象,emplace_back
不是对象时,例如1
2
3
4
5
6
7std::vector<President> elections;
std::cout << "emplace_back:\n";
elections.emplace_back("Franklin Delano Roosevelt", "the USA", 1936);
std::vector<President> reElections;
std::cout << "\npush_back:\n";
reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));如果对象有移动构造函数,两者性能差距不大,
emplace_back
会快一点。push_back
会调用一次构造函数。emplace_back
会调用一次构造函数,再调用一次移动构造函数,会慢一点。如果对象没有移动构造函数,
emplace_back
会快很多。push_back
会调用一次构造函数。emplace_back
会调用一次构造函数,再调用一次拷贝构造函数,性能差距比较大。
push_back的类别的拷贝构造函数参数如果不是const会出现错误
push_back()
有四种形式。
1 |
|
对于非右值时,把对象转换成const
,之后会调用拷贝构造函数,当拷贝构造函数不加const
时,会尝试把const
对象转换为非const
对象,引起错误。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!