std::vector<T,Allocator>::emplace
来自cppreference.com
template< class... Args > iterator emplace( const_iterator pos, Args&&... args ); |
(C++11 起) (C++20 起为 constexpr ) |
|
在紧接 pos 之前的位置向容器插入新元素。
通过 std::allocator_traits::construct 构造元素,常用布置 new 在容器提供的位置原位构造元素。然而若要求的位置已被既存的元素占据,则首先在另一位置构造被插入的元素,然后再将它移动赋值到要求的位置中。
将实参 args... 作为 std::forward<Args>(args)... 转发给构造函数。 args... 可以直接或间接地指代容器中的值。
如果操作后新的 size()
大于原 capacity()
则会发生重分配,这种情况下,指代元素的所有迭代器(包括 end()
迭代器)和所有引用均会失效。否则,仅插入点之前的迭代器和引用保持有效。
参数
pos | - | 将构造新元素到其前的迭代器 |
args | - | 转发给元素构造函数的参数 |
类型要求 | ||
-T(容器的元素类型) 必须满足可移动赋值 (MoveAssignable) 、可移动插入 (MoveInsertable) 和 可就位构造 (EmplaceConstructible) 。
|
返回值
指向被安置的元素的迭代器。
复杂度
与 pos
和容器尾的距离成线性。
异常
若 T
的复制构造函数、移动构造函数、赋值运算符或移动赋值运算符以外的操作抛出了异常,或若在用 emplace
在尾部插入单个元素时抛出了异常,且 T
可复制插入或可不抛出移动构造,则无效果(强异常保证)。
否则,效果未指定。
示例
运行此代码
#include <iostream> #include <string> #include <vector> struct A { std::string s; A(std::string str) : s(std::move(str)) { std::cout << " 构造\n"; } A(const A& o) : s(o.s) { std::cout << " 复制构造\n"; } A(A&& o) : s(std::move(o.s)) { std::cout << " 移动构造\n"; } A& operator=(const A& other) { s = other.s; std::cout << " 复制赋值\n"; return *this; } A& operator=(A&& other) { s = std::move(other.s); std::cout << " 移动赋值\n"; return *this; } }; int main() { std::vector<A> container; // 预留足够的空间以使 vector 不必重设大小 container.reserve(10); std::cout << "构造 2 次 A:\n"; A two{"two"}; A three{"three"}; std::cout << "emplace:\n"; container.emplace(container.end(), "one"); std::cout << "以 A& 调用 emplace:\n"; container.emplace(container.end(), two); std::cout << "以 A&& 调用 emplace:\n"; container.emplace(container.end(), std::move(three)); std::cout << "内容:\n"; for (const auto& obj : container) std::cout << ' ' << obj.s; std::cout << '\n'; }
输出:
构造 2 次 A: 构造 构造 emplace: 构造 以 A& 调用 emplace: 复制构造 以 A&& 调用 emplace: 移动构造 内容: one two three
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
LWG 2164 | C++11 | 不清楚参数是否能指代容器 | 已澄清 |
参阅
插入元素 (公开成员函数) | |
(C++11) |
在容器末尾原位构造元素 (公开成员函数) |