为什么 std::map 的移动构造函数不是 noexcept?
Why is std::map's move constructor not noexcept?
正如 cppreference.com 所说,
地图通常实现为红黑树。
因此,移动std::map
只是将指针移动到根node
+ 其他信息(如大小)。为什么std::map
的移动构造函数没有标记为noexcept
?
这是因为我无法将所有实现者都置于可以放入map
的无资源状态。 例如,实现需要有一个要指向的终端节点,即使在默认构造状态下也是如此。 允许(但不是必需)实现将该终端节点放在堆上。
移自映射必须处于有效状态。 即,当调用end()
时,移自map
必须有一个指向的结束节点。在移动构造之前,map
中存在一个要从中移动的终端节点。在移动构造之后,必须存在两个终端节点:一个在新map
中,另一个在移自"地图"中。
如果终端节点进入堆,这意味着移动构造函数要么不转移结束节点的所有权,因此必须为新的"映射"分配新的结束节点。或者确实转移了终端节点,但随后必须分配一个新节点以保留在移自源中。
如果终端节点嵌入在map
数据结构本身中,则永远不需要在堆上分配它。 随着map
的构建,它会自动"在堆栈上分配"。
允许实现使map
移动构造函数noexcept
如果他们愿意,他们只是不需要这样做。
以下是我几年前进行的实现中容器的默认构造函数、移动构造函数和移动赋值运算符的 noexexcept 状态的调查。 此调查假定每个容器std::allocator
。 我只是抽查了map
,结果没有改变。
如果您想自己运行此调查,以下是代码:
#include "type_name.h"
#include <iostream>
#include <type_traits>
#include <deque>
#include <forward_list>
#include <list>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
template <class C>
void
report()
{
using namespace std;
const auto name = type_name<C>();
if (is_nothrow_default_constructible<C>::value)
std::cout << name << " is noexcept default constructiblen";
else
std::cout << name << " is NOT noexcept default constructiblen";
if (is_nothrow_move_constructible<C>::value)
std::cout << name << " is noexcept move constructiblen";
else
std::cout << name << " is NOT noexcept move constructiblen";
if (is_nothrow_move_assignable<C>::value)
std::cout << name << " is noexcept move assignablenn";
else
std::cout << name << " is NOT noexcept move assignablenn";
}
int
main()
{
using namespace std;
report<deque<int>>();
report<forward_list<int>>();
report<list<int>>();
report<vector<int>>();
report<string>();
report<map<int, int>>();
report<set<int>>();
report<unordered_map<int, int>>();
report<unordered_set<int>>();
}
"type_name.h"
从这个答案中来。
相关文章:
- 为什么 std::map 的移动构造函数不是 noexcept?
- 查找所有移动构造函数和移动赋值运算符(特别是那些没有"noexcept"的运算符)
- 为什么noexcept move构造函数在向量重新分配期间没有被调用
- MSVC 2017中STL容器的移动构造函数未标记为NOExcept
- 对于具有抛出复制构造函数和noexcept-by-value复制赋值的类,is_nothrow_copy_assigna
- 是复制构造函数中初始值设定项列表中的make_unique不使用noexcept说明符的好用途
- 在向量中使用不带复制且没有 noexcept 移动构造函数的对象.实际损坏的内容以及我如何确认它
- is_nothrow_default_constructible具有noexcept(false)默认构造函数
- 如何声明包装器类型 X 的移动构造函数<T> noexcept 取决于is_nothrow_move_constructible<T>?
- 为什么 g++ 不发出这个与构造函数相关的 noexcept 启用"-fpic"的警告?
- 我应该声明我的异常的副本构造函数noexcept吗
- 具有 GCC 接受"noexcept"构造函数的程序,被 clang 拒绝
- 派生类构造函数上的Noexcept promise:可以在没有对基构造函数上的Noexcept进行承诺的情况下使用
- 对于默认定义的移动构造函数,noexcept的规则是什么
- 从 noexcept 函数参数的构造函数引发的异常会立即导致对 std::terminate() 的调用吗?
- 默认情况下是默认的构造函数/赋值noexcept/constexpr
- 默认情况下继承构造函数 noexcept(true)
- 确定抽象基类的构造函数是否为 noexcept
- 编译器何时将默认生成的构造函数标记为 noexcept
- 为什么noexcept构造函数需要析构函数的实例化