std::optional<T>::operator=
来自 cppreference.com
optional& operator=( std::nullopt_t ) noexcept; |
(1) | (自 C++17 起) (自 C++20 起为 constexpr) |
constexpr optional& operator=( const optional& other ); |
(2) | (自 C++17 起) |
constexpr optional& operator=( optional&& other ) noexcept(/* see below */); |
(3) | (自 C++17 起) |
template< class U = T > optional& operator=( U&& value ); |
(4) | (自 C++17 起) (自 C++20 起为 constexpr) |
template< class U > optional& operator=( const optional<U>& other ); |
(5) | (自 C++17 起) (自 C++20 起为 constexpr) |
template< class U > optional& operator=( optional<U>&& other ); |
(6) | (自 C++17 起) (自 C++20 起为 constexpr) |
用 *this 的内容替换 other 的内容。
1) 如果 *this 在调用之前包含一个值,则包含的值将通过调用其析构函数来销毁,就好像通过 value().T::~T() 一样。 *this 在此调用之后不包含任何值。
2,3) 分配 other 的状态。
- 如果 *this 和 other 都没有包含值,则函数没有效果。
- 如果 *this 包含一个值,但 other 不包含,则包含的值将通过调用其析构函数来销毁。 *this 在调用之后不包含任何值。
- 如果 other 包含一个值,则根据 *this 是否包含一个值,包含的值要么被直接初始化,要么从 *other 分配 (2) 或 std::move(*other) (3)。 请注意,一个被移动的 optional 仍然包含一个值。
- 当 std::is_copy_constructible_v<T> 或 std::is_copy_assignable_v<T> 为 false 时,重载 (2) 将被删除。 如果 std::is_trivially_copy_constructible_v<T>、std::is_trivially_copy_assignable_v<T> 和 std::is_trivially_destructible_v<T> 全部为 true,则它将是平凡的。
- 当 std::is_move_constructible_v<T> 或 std::is_move_assignable_v<T> 为 false 时,重载 (3) 不会参与重载解析。 如果 std::is_trivially_move_constructible_v<T>、std::is_trivially_move_assignable_v<T> 和 std::is_trivially_destructible_v<T> 全部为 true,则它将是平凡的。
4) 完美转发赋值:取决于调用之前*this是否包含值,包含的值要么从std::forward<U>(value)直接初始化,要么从std::forward<U>(value)赋值。除非std::decay_t<U>(直到 C++20)std::remove_cvref_t<U>(从 C++20 开始)不是std::optional<T>,std::is_constructible_v<T, U>为true,std::is_assignable_v<T&, U>为true,并且以下至少一项为真,该函数才参与重载解析。
-
T
不是标量类型; - std::decay_t<U>不是
T
。
5,6) 将other的状态赋予自身。
- 如果 *this 和 other 都没有包含值,则函数没有效果。
- 如果 *this 包含一个值,但 other 不包含,则包含的值将通过调用其析构函数来销毁。 *this 在调用之后不包含任何值。
- 如果other包含值,则取决于*this是否包含值,包含的值要么是直接初始化的,要么从*other (5)或std::move(*other) (6)赋值。请注意,已移动的可选对象仍然包含一个值。
- 除非满足以下条件,否则这些重载不会参与重载解析。
-
T
不能从任何类型为(可能是const)std::optional<U>的表达式构造、转换或赋值,即以下 12 个类型特征都是false- std::is_constructible_v<T, std::optional<U>&>
- std::is_constructible_v<T, const std::optional<U>&>
- std::is_constructible_v<T, std::optional<U>&&>
- std::is_constructible_v<T, const std::optional<U>&&>
- std::is_convertible_v<std::optional<U>&, T>
- std::is_convertible_v<const std::optional<U>&, T>
- std::is_convertible_v<std::optional<U>&&, T>
- std::is_convertible_v<const std::optional<U>&&, T>
- std::is_assignable_v<T&, std::optional<U>&>
- std::is_assignable_v<T&, const std::optional<U>&>
- std::is_assignable_v<T&, std::optional<U>&&>
- std::is_assignable_v<T&, const std::optional<U>&&>
- 对于重载 (5),std::is_constructible_v<T, const U&> 和 std::is_assignable_v<T&, const U&> 都是 true。
- 对于重载 (6),std::is_constructible_v<T, U> 和 std::is_assignable_v<T&, U> 都是 true。
-
内容 |
[编辑] 参数
other | - | 另一个optional 对象,其包含的值要赋值。 |
value | - | 要赋值给包含值的 value。 |
[编辑] 返回值
*this
[编辑] 异常
2-6) 抛出
T
的构造函数或赋值运算符抛出的任何异常。如果抛出异常,则*this(以及(2,3) 和 (5,6) 的other)的初始化状态保持不变,即如果对象包含值,它仍然包含值,反之亦然。value 的内容以及*this 和other 的包含值取决于异常源自的操作(复制构造函数、移动赋值运算符等)的异常安全保障。3) 具有以下
noexcept 规范:
noexcept(std::is_nothrow_move_assignable_v<T> && std::is_nothrow_move_constructible_v<T>)
[编辑] 说明
可选对象 op
可以通过op = {}; 和op = nullopt; 转换为一个空可选对象。第一个表达式用{} 构造一个空optional 对象,并将其赋值给 op
。
特性测试 宏 | 值 | Std | 特性 |
---|---|---|---|
__cpp_lib_optional |
202106L | (C++20) (DR20) |
完全constexpr (1),(4-6) |
[编辑] 示例
运行此代码
#include <iostream> #include <optional> int main() { std::optional<const char*> s1 = "abc", s2; // constructor s2 = s1; // assignment s1 = "def"; // decaying assignment (U = char[4], T = const char*) std::cout << *s2 << ' ' << *s1 << '\n'; }
输出
abc def
[编辑] 缺陷报告
以下行为变更缺陷报告被追溯应用到之前发布的 C++ 标准。
DR | 应用于 | 已发布的行为 | 正确的行为 |
---|---|---|---|
P0602R4 | C++17 | 复制/移动赋值运算符可能不是平凡的 即使底层操作是平凡的 |
要求传播平凡性 |
P2231R1 | C++20 | 转换赋值运算符 (1) 和 (4-6) 不是 constexpr 虽然在 C++20 中所需的操作可以是 |
已改为 constexpr |
[编辑] 另请参阅
在原地构造包含的值 (公共成员函数) |