std::optional<T>::emplace
来自cppreference.com
<tbody>
</tbody>
template< class... Args > T& emplace( Args&&... args ); |
(1) | (C++17 起) (C++20 起为 constexpr) |
template< class U, class... Args > T& emplace( std::initializer_list<U> ilist, Args&&... args ); |
(2) | (C++17 起) (C++20 起为 constexpr) |
原位构造所含值。若 *this 已在此调用前含值,则调用其析构函数销毁所含值。
2) 以
ilist, std::forward<Args>(args)... 为参数直接初始化(但不是直接列表初始化)所含值。此重载只有在 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value 为 true 时才会参与重载决议。参数
| args... | - | 传递给构造函数的实参 |
| ilist | - | 传递给构造函数的初始化式列表 |
| 类型要求 | ||
-对于重载 (1),T 必须可从 Args... 构造
| ||
-对于重载 (2),T 必须可从 std::initializer_list 及 Args... 构造
| ||
返回值
到新的所含值的引用。
异常
被选中的 T 构造函数所抛出的任何异常。若抛出异常,则 *this 在此调用后不含值(若先前存在所含值,则销毁它)。
注解
| 功能特性测试宏 | 值 | 标准 | 功能特性 |
|---|---|---|---|
__cpp_lib_optional |
202106L |
(C++20) (DR20) |
完全 constexpr (1,2)
|
示例
运行此代码
#include <iostream>
#include <optional>
struct A
{
std::string s;
A(std::string str) : s(std::move(str)), id{n++} { note("+ 构造"); }
~A() { note("~ 析构"); }
A(const A& o) : s(o.s), id{n++} { note("+ 复制构造"); }
A(A&& o) : s(std::move(o.s)), id{n++} { note("+ 移动构造"); }
A& operator=(const A& other)
{
s = other.s;
note("= 复制赋值");
return *this;
}
A& operator=(A&& other)
{
s = std::move(other.s);
note("= 移动赋值");
return *this;
}
inline static int n{};
int id{};
void note(auto s) { std::cout << " " << s << " #" << id << '\n'; }
};
int main()
{
std::optional<A> opt;
std::cout << "赋值:\n";
opt = A("Lorem ipsum dolor sit amet, consectetur adipiscing elit nec.");
std::cout << "放置:\n";
// 由于 opt 含值,这亦将销毁该值
opt.emplace("Lorem ipsum dolor sit amet, consectetur efficitur. ");
std::cout << "示例结束\n";
}
输出:
赋值:
+ 构造 #0
+ 移动构造 #1
~ 析构 #0
放置:
~ 析构 #1
+ 构造 #2
示例结束
~ 析构 #2
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| 缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
|---|---|---|---|
| P2231R1 | C++20 | emplace 不是 constexpr,而要求的操作在 C++20 中能为 constexpr
|
使之为 constexpr
|
参阅
| 对内容赋值 (公开成员函数) |