为什么std :: vector尽管声明为noexcept(false),但仍使用move构造函数 [英] Why does std::vector use the move constructor although declared as noexcept(false)

查看:183
本文介绍了为什么std :: vector尽管声明为noexcept(false),但仍使用move构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

无论我在网上读什么书,都强烈建议如果我希望我的班级与std::vector一起正常工作(即,我班级的移动语义被std::vector使用),我应该将care构造函数的delcare移动为'noexcept '(或noexcept(true)).

Wherever I read in the internet, it is strongly adviced that if I want my class to be working well with std::vector (i.e. move semantics from my class were used by std::vector) I should delcare move constructor as 'noexcept' ( or noexcept(true) ).

#include <iostream>
#include <vector>
using std::cout;

struct T
{
    T() { cout <<"T()\n"; }

    T(const T&) { cout <<"T(const T&)\n"; }

    T& operator= (const T&)
    { cout <<"T& operator= (const T&)\n"; return *this; }

    ~T() { cout << "~T()\n"; }

    T& operator=(T&&) noexcept(false)
    { cout <<"T& operator=(T&&)\n"; return *this; }

    T(T&&) noexcept(false)
    { cout << "T(T&&)\n"; }
};

int main()
{
    std::vector<T> t_vec;
    t_vec.push_back(T());
}

输出:

T()
T(T&&)
~T()
~T()

为什么? 我做错了什么?

Why ? What did I do wrong ?

在gcc 4.8.2上编译,并将CXX_FLAGS设置为:

Compiled on gcc 4.8.2 with CXX_FLAGS set to:

--std=c++11 -O0 -fno-elide-constructors

推荐答案

您没有做错任何事情.

您只是错误地认为push_back必须避免抛出move-ctor:至少在构造新元素时不需要这样做.

You just wrongly thought push_back had to avoid a throwing move-ctor: It does not, at least for constructing the new element.

必须避免唯一的抛出动圈/移动分配的地方是重新分配向量,以避免移动一半的元素,而其余的保留在其原始位置.

The only place where throwing move-ctors / move-assignments must be shunned is on re-allocation of the vector, to avoid having half the elements moved, and the rest in their original places.

该功能具有强大的异常安全保证:

The function has the strong exception-safety guarantee:

要么操作成功,要么操作失败,但没有任何改变.

Either the operation succeeds, or it fails and nothing has changed.

这篇关于为什么std :: vector尽管声明为noexcept(false),但仍使用move构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆