使用没有副本的对象,并且在向量中没有noexcept移动构造函数.什么打破了,我该如何确认?

Xen*_*ial 9 c++ constructor move vector c++11

我已经检查了很多移动构造函数/ vector/noexcept线程,但我仍然不确定当事情出错时会发生什么.我期望的时候不会产生错误,所以要么我的小测试错了,要么我对问题的理解是错误的.

我正在使用一个BufferTrio对象的向量,它定义了一个noexcept(false)移动构造函数,并删除了所有其他构造函数/赋值运算符,以便没有任何内容可以回退到:

    BufferTrio(const BufferTrio&) = delete;
    BufferTrio& operator=(const BufferTrio&) = delete;
    BufferTrio& operator=(BufferTrio&& other) = delete;

    BufferTrio(BufferTrio&& other) noexcept(false)
        : vaoID(other.vaoID)
        , vboID(other.vboID)
        , eboID(other.eboID)
    {
        other.vaoID = 0;
        other.vboID = 0;
        other.eboID = 0;
    }
Run Code Online (Sandbox Code Playgroud)

编译和运行的东西,但从https://xinhuang.github.io/posts/2013-12-31-when-to-use-noexcept-and-when-to-not.html:

std :: vector将在需要增加(或减少)容量时使用move,只要移动操作为noexcept即可.

或者来自优化的C++:经过验证的高性能技术作者:Kurt Guntheroth:

如果移动构造函数和移动赋值运算符未声明为noexcept,则std :: vector使用效率较低的复制操作.

既然我删除了那些,我的理解是应该在这里打破一些东西.但是这个载体的运行正常.所以我还创建了一个基本循环,将push_backs五十万次转换为一个虚拟向量,然后将该向量与另一个单元素虚拟​​向量交换.像这样:

    vector<BufferTrio> thing;

    int n = 500000;
    while (n--)
    {
        thing.push_back(BufferTrio());
    }

    vector<BufferTrio> thing2;
    thing2.push_back(BufferTrio());

    thing.swap(thing2);
    cout << "Sizes are " << thing.size() << " and " << thing2.size() << endl;
    cout << "Capacities are " << thing.capacity() << " and " << thing2.capacity() << endl;
Run Code Online (Sandbox Code Playgroud)

输出:

Sizes are 1 and 500000
Capacities are 1 and 699913
Run Code Online (Sandbox Code Playgroud)

仍然没有问题,所以:

我是否应该看到出错的地方,如果出现问题,我该如何证明?

Ker*_* SB 10

向量重新分配尝试提供异常保证,即在重新分配操作期间抛出异常时尝试保留原始状态.有三种情况:

  1. 元素类型是nothrow_move_constructible:重新分配可以移动不会导致异常的元素.这是有效的案例.

  2. 元素类型是CopyInsertable:如果类型不成nothrow_move_constructible,则这足以提供强有力的保证,尽管在重新分配期间进行了复制.这是旧的C++ 03默认行为,效率较低.

  3. 元素类型既不是也不CopyInsertablenothrow_move_constructible.只要它仍然是可移动构造的,就像在你的例子中一样,向量重新分配是可能的,但是不提供任何异常保证(例如,如果移动构造抛出,你可能会丢失元素).

说明这一点的规范性措辞分散在各种重新分配功能中.例如,[vector.modifiers]/push_back表示:

如果在在端部插入单个元件和抛出异常TCopyInsertableis_nothrow_move_constructible_v<T>true,没有影响.否则,如果非移动构造函数抛出异常,CopyInsertable T则不指定效果.

我不知道你引用的帖子的作者是什么,虽然我可以想象他们隐含地假设你想要强烈的异常保证,所以他们想引导你进入案例(1)或( 2).