跳到主要内容

std::vector emplace() 方法

// prism-push-types:iterator,const_iterator
// Non const version only
template< class... Args >
constexpr iterator emplace( const_iterator pos, Args&&... args );

在 `pos` 之前直接将一个新元素插入到容器中。

该元素通过 `std::allocator_traits::construct()` 构造,这通常使用 placement-new 在容器提供的位置原地构造元素。但是,如果所需位置已被现有元素占用,则插入的元素首先在另一个位置构造,然后移动赋值到所需位置。

参数 `args...` 作为 `std::forward(args)...` 转发给构造函数。`args...` 可以直接或间接引用容器中的值。

失效

如果新的 `size()` 大于 `capacity()`,则所有迭代器引用都将失效。

否则,只有插入点之前的迭代器引用保持有效

末尾迭代器也会失效。

参数

  • `pos` - 新元素将被构造的迭代器位置
  • args - 转发给元素构造函数的参数

类型要求

返回值

指向插入元素的迭代器

复杂度

与 `pos` 到容器末尾的距离呈线性关系 - O(std::distance(pos, end()))

异常

如果除了值类型的拷贝构造函数移动构造函数赋值运算符移动赋值运算符之外抛出异常,

或者在使用 `emplace()` 在末尾插入单个元素时抛出异常,并且值类型是 `CopyInsertable` 或 nothrow 可移动构造的,则没有副作用(强异常保证)。

否则,效果未指定.

示例

Main.cpp
#include <iostream>
#include <string>
#include <vector>

struct A {
std::string s;
A(std::string str) : s(std::move(str)) { std::cout << " constructed\n"; }
A(const A& o) : s(o.s) { std::cout << " copy constructed\n"; }
A(A&& o) : s(std::move(o.s)) { std::cout << " move constructed\n"; }
A& operator=(const A& other) {
s = other.s;
std::cout << " copy assigned\n";
return *this;
}
A& operator=(A&& other) {
s = std::move(other.s);
std::cout << " move assigned\n";
return *this;
}
};

int main()
{
std::vector<A> container;
// reserve enough place so vector does not have to resize
container.reserve(10);
std::cout << "construct 2 times A:\n";
A two { "two" };
A three { "three" };

std::cout << "emplace:\n";
container.emplace(container.end(), "one");

std::cout << "emplace with A&:\n";
container.emplace(container.end(), two);

std::cout << "emplace with A&&:\n";
container.emplace(container.end(), std::move(three));

std::cout << "content:\n";
for (const auto& obj : container)
std::cout << ' ' << obj.s;
std::cout << '\n';
}
输出
construct 2 times A:
constructed
constructed
emplace:
constructed
emplace with A&:
copy constructed
emplace with A&&:
move constructed
content:
one two three
本文源自此 CppReference 页面。它可能为了改进或编辑者的偏好而进行了修改。点击“编辑此页面”查看本文档所做的所有更改。
悬停查看原始许可证。

std::vector emplace() 方法

// prism-push-types:iterator,const_iterator
// Non const version only
template< class... Args >
constexpr iterator emplace( const_iterator pos, Args&&... args );

在 `pos` 之前直接将一个新元素插入到容器中。

该元素通过 `std::allocator_traits::construct()` 构造,这通常使用 placement-new 在容器提供的位置原地构造元素。但是,如果所需位置已被现有元素占用,则插入的元素首先在另一个位置构造,然后移动赋值到所需位置。

参数 `args...` 作为 `std::forward(args)...` 转发给构造函数。`args...` 可以直接或间接引用容器中的值。

失效

如果新的 `size()` 大于 `capacity()`,则所有迭代器引用都将失效。

否则,只有插入点之前的迭代器引用保持有效

末尾迭代器也会失效。

参数

  • `pos` - 新元素将被构造的迭代器位置
  • args - 转发给元素构造函数的参数

类型要求

返回值

指向插入元素的迭代器

复杂度

与 `pos` 到容器末尾的距离呈线性关系 - O(std::distance(pos, end()))

异常

如果除了值类型的拷贝构造函数移动构造函数赋值运算符移动赋值运算符之外抛出异常,

或者在使用 `emplace()` 在末尾插入单个元素时抛出异常,并且值类型是 `CopyInsertable` 或 nothrow 可移动构造的,则没有副作用(强异常保证)。

否则,效果未指定.

示例

Main.cpp
#include <iostream>
#include <string>
#include <vector>

struct A {
std::string s;
A(std::string str) : s(std::move(str)) { std::cout << " constructed\n"; }
A(const A& o) : s(o.s) { std::cout << " copy constructed\n"; }
A(A&& o) : s(std::move(o.s)) { std::cout << " move constructed\n"; }
A& operator=(const A& other) {
s = other.s;
std::cout << " copy assigned\n";
return *this;
}
A& operator=(A&& other) {
s = std::move(other.s);
std::cout << " move assigned\n";
return *this;
}
};

int main()
{
std::vector<A> container;
// reserve enough place so vector does not have to resize
container.reserve(10);
std::cout << "construct 2 times A:\n";
A two { "two" };
A three { "three" };

std::cout << "emplace:\n";
container.emplace(container.end(), "one");

std::cout << "emplace with A&:\n";
container.emplace(container.end(), two);

std::cout << "emplace with A&&:\n";
container.emplace(container.end(), std::move(three));

std::cout << "content:\n";
for (const auto& obj : container)
std::cout << ' ' << obj.s;
std::cout << '\n';
}
输出
construct 2 times A:
constructed
constructed
emplace:
constructed
emplace with A&:
copy constructed
emplace with A&&:
move constructed
content:
one two three
本文源自此 CppReference 页面。它可能为了改进或编辑者的偏好而进行了修改。点击“编辑此页面”查看本文档所做的所有更改。
悬停查看原始许可证。