C++11 emplace_back和push_back的区别
push_back
void push_back( const T& value ); | |
void push_back( T& value ); | (C++11 起) |
后附给定元素 value
到容器尾。
1) 初始化新元素为 value
的副本。
2) 移动 value
进新元素。
若新的 size() 大于 capacity() ,则所有迭代器和引用(包含尾后迭代器)都被非法化。否则仅尾后迭代器被非法化。
参数
value 要后附的元素值。
为使用重载,T必须满足可复制插入和可移动插入的要求。
返回值
无
复杂度
常数。
异常
若抛出异常(可能因为 Allocator::allocate()
或元素复制/移动构造函数/赋值),则此函数无效果(强异常保证)。
注意
一些实现在 push_back
导致会超出 max_size 的重分配时亦抛出 std::length_error ,由于这会隐式调用 reserve(size()+1) 的等价者。
示例
#include <vector>
#include <iostream>
#include <iomanip>
int main()
{
std::vector<std::string> numbers;
numbers.push_back("abc");
std::string s = "def";
numbers.push_back(std::move(s));
std::cout << "vector holds: ";
for (auto&& i : numbers) std::cout << std::quoted(i) << ' ';
std::cout << "\nMoved-from string holds " << std::quoted(s) << '\n';
}
输出:
emplace_back
template< class... Args > void emplace_back( Args&&... args ); |
(C++11起,C++17前) |
template< class... Args > reference emplace_back( Args&&... args ); |
(C++17起) |
添加新元素到容器尾。元素通过 std::allocator_traits::construct 构造,它典型地用布置 new 于容器所提供的位置原位构造元素。参数 args...
以 std::forward<Args>(args)... 转发到构造函数。
所有迭代器,包含尾后迭代器,都被非法化。没有引用被非法化。
参数
args 转发到元素构造函数的参数
返回值
(无) | C++17前 |
被插入元素的引用 | C++17起 |
复杂度
常数
异常
若抛出异常,则此函数无效果(强异常保证)。
示例
下列代码用 emplace_back
后附 President
类型对象到 std::deque 。它演示 emplace_back
如何转发参数到 President
的构造函数,并展示如何用 emplace_back
避免用 push_back
时的额外复制或移动操作。
#include <deque>
#include <string>
#include <iostream>
struct President
{
std::string name;
std::string country;
int year;
President(std::string p_name, std::string p_country, int p_year)
: name(std::move(p_name)), country(std::move(p_country)), year(p_year)
{
std::cout << "I am being constructed.\n";
}
President(President&& other)
: name(std::move(other.name)), country(std::move(other.country)), year(other.year)
{
std::cout << "I am being moved.\n";
}
President& operator=(const President& other) = default;
};
int main()
{
std::deque<President> elections;
std::cout << "emplace_back:\n";
elections.emplace_back("Nelson Mandela", "South Africa", 1994);
std::deque<President> reElections;
std::cout << "\npush_back:\n";
reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));
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";
}
}
输出:
比较
emplace_back:在容器末尾就地构造元素,push_back则没有这个机制,还有push_back的使用可能会导致额外的复制或移动操作。
参考:
https://zh.cppreference.com/w/cpp/container/deque/emplace_back