c – 移动哪个投掷?

c – 移动哪个投掷?,第1张

概述据我所知,move-constructors和move-assign必须标记为noexcept,以便编译器在例如在向量内重新分配时使用它们. 但是,是否存在任何真实情况,其中move-assign,move-construct可能实际抛出? 更新: 例如,当构造不能进行无掷移动时,具有已分配资源的类. However, is there any real-world case where a mo 据我所知,move-constructors和move-assign必须标记为noexcept,以便编译器在例如在向量内重新分配时使用它们.

但是,是否存在任何真实情况,其中move-assign,move-construct可能实际抛出?

更新:

例如,当构造不能进行无掷移动时,具有已分配资源的类.

解决方法

However,is there any real-world case where a move-assign,
move-construct (or swap) might actually throw?

是.考虑std :: List的实现.结束迭代器必须在列表中指向“一个超过最后一个元素”.存在std :: List的实现,其中什么是指向动态分配的节点.即使是默认构造函数也会分配这样一个节点,这样当你调用end()时,有一些东西需要指向.

在这样的实现中,每个构造函数都必须为end()分配一个节点以指向…甚至移动构造函数.该分配可能会失败,并抛出异常.

此相同的行为可以扩展到任何基于节点的容器.

还有一些基于节点的容器的实现,它们进行“短串”优化:它们将端节点嵌入容器类本身,而不是动态分配.因此默认构造函数(和移动构造函数)不需要分配任何东西.

移动赋值运算符可以抛出任何容器< X>如果容器的分配器propagate_on_container_move_assignment :: value为false,并且lhs中的分配器不等于rhs中的分配器.在这种情况下,禁止移动赋值运算符将内存所有权从rhs转移到lhs.如果您使用std :: allocator,则不会发生这种情况,因为std :: allocator的所有实例彼此相等.

更新

以下是propagate_on_container_move_assignment :: value为false时的一致性和可移植示例.它已经过最新版VS,gcc和clang的测试.

#include <cassert>#include <cstddef>#include <iostream>#include <vector>template <class T>class allocator{    int ID_;public:    using value_type    = T;    allocator(int ID) noexcept : ID_(ID) {}    template <class U> allocator(allocator<U> const& u) noexcept : ID_(u.ID_) {}    value_type*    allocate(std::size_t n)    {        return static_cast<value_type*>(::operator new (n*sizeof(value_type)));    }    voID    deallocate(value_type* p,std::size_t) noexcept    {        ::operator delete(p);    }    template <class U,class V>    frIEnd    bool    operator==(allocator<U> const& x,allocator<V> const& y) noexcept    {        return x.ID_ == y.ID_;    }};template <class T,class U>booloperator!=(allocator<T> const& x,allocator<U> const& y) noexcept{    return !(x == y);}template <class T> using vector = std::vector<T,allocator<T>>;struct A{    static bool time_to_throw;    A() = default;    A(const A&) {if (time_to_throw) throw 1;}    A& operator=(const A&) {if (time_to_throw) throw 1; return *this;}};bool A::time_to_throw = false;intmain(){    vector<A> v1(5,A{},allocator<A>{1});    vector<A> v2(allocator<A>{2});    v2 = std::move(v1);    try    {        A::time_to_throw = true;        v1 = std::move(v2);        assert(false);    }    catch (int i)    {        std::cout << i << '\n';    }}

该计划输出:

1

这表示载体< T,A>当propagate_on_container_move_assignment :: value为false并且有问题的两个分配器不比较相等时,move赋值运算符是复制/移动其元素.如果这些副本/移动中的任何一个抛出,则容器移动分配抛出.

总结

以上是内存溢出为你收集整理的c – 移动哪个投掷?全部内容,希望文章能够帮你解决c – 移动哪个投掷?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1233400.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存