gpt4 book ai didi

c++ - 如果类包含标准容器,我可以将类 move 操作标记为 noexcept 吗?

转载 作者:可可西里 更新时间:2023-11-01 16:36:23 24 4
gpt4 key购买 nike

在具有标准容器成员的类上实现 move 操作的惯用方法不能是 noexcept 因此不能通过 vector.push_back() 等操作 move .还是我弄错了?

从中获取速度

vector<Elem> data;
// ...
data.push_back( elem );

鼓励我们进行 move 操作noexcept -- 因此在 vector 调整大小时,库可以安全地将元素 move 到重新分配的存储空间。

class Elem {
// ...
Elem(Elem&&) noexcept; // noexcept important for move
Elem& operator=(Elem&&) noexcept; // noexcept important for move
};

到目前为止一切顺利,现在是我的 elem可以更快地推回 s。

但是:如果我添加一个容器作为成员,我的类是否仍会被标记为 noexcept-move?所有标准容器都有它们的 move noexcept !

class Stuff {
vector<int> bulk;
// ...
Stuff(Stuff&& o) // !!! no noexcept because of vector-move
: bulk(move(o.bulk))
{}
Stuff& operator=(Stuff&&) // !!! no noexcept...
{ /* appropriate implementation */ }
};

这也意味着,我们也不能依赖编译器生成的 move 操作,对吧?下面的完整类也不会有noexcept - move 操作,因此不是“快速”,对吗?

struct Holder {
vector<int> bulk;
};

也许 vector<int> move 起来有点太简单了,但是vector<Elem>呢? ?

这将对所有以容器为成员的数据结构产生重大影响。

最佳答案

我真的感觉到你的痛苦。

一些 std::implementations 将容器的 move 成员标记为 noexcept,至少以分配器属性为条件,作为扩展。您可以调整代码以自动利用这些扩展,例如:

class Stuff {
std::vector<int> bulk;
// ...
public:
Stuff(Stuff&& o)
noexcept(std::is_nothrow_move_constructible<std::vector<int>>::value)
: bulk(std::move(o.bulk))
{}
Stuff& operator=(Stuff&&)
noexcept(std::is_nothrow_move_assignable<std::vector<int>>::value)
{ /* appropriate implementation */ }
};

你甚至可以测试你的类型是否有 noexcept move 成员:

static_assert(std::is_nothrow_move_constructible<Stuff>::value,
"I hope Stuff has noexcept move members");
static_assert(std::is_nothrow_move_assignable<Stuff>::value,
"I hope Stuff has noexcept move members");

libc++特别是它的所有容器都具有 noexcept move 成员,只要分配器允许,并且 std::allocator 始终允许容器 move 成员为 noexcept。

关于c++ - 如果类包含标准容器,我可以将类 move 操作标记为 noexcept 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21320391/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com