编译器没有使用move c'tor / assignment oper?

时间:2015-03-19 17:59:15

标签: c++ move-semantics

真的很简单的问题。以下示例代码中发生了什么导致它无法编译?

错误发生在main()的第一行:

  

"使用已删除的功能' std::__atomic0::...__atomic_base(...)')"

#include <atomic>
#include <deque>
#include <vector>

using namespace std;

class Test {
public:
    deque<atomic_int> dq;
    Test(){}
};


int main(){
    vector<Test> v = { Test(), Test() };

    return 0;
}

我将其编译为c ++ 0x代码,我理解atomic类型可能无法复制?但无论哪种方式,行vector<Test> v = { Test(), Test() };都应该调用Test的默认 move 构造函数/赋值运算符,它应该调用 move 构造函数/赋值Test::dq的运算符,无需复制任何atomic_int

那么为什么要编译呢?

修改

我的编译器允许我将不可移动的对象添加到容器中,然后移动容器。见下文:

class Test {
public:
    deque<atomic_int> dq;
    Test(){
        dq.resize(10);
    }
};


int main(){
    Test t1;
    Test t2(std::move(t1));

    return 0;
}

t1上执行移动,该移动会调用t1个成员的移动,其中一个成员为deque。因此,deque中的每个成员都会移动,其中没有一个属于atomic_int

类型

1 个答案:

答案 0 :(得分:3)

从C ++ 11开始,拥有一个只有默认可构造对象的容器是完全合法的,前提是你不要使用任何需要对象可复制或移动的操作。

但是,std::initializer_list仅允许const访问其元素,这意味着您无法移动它们。因此

vector<Test> v = { Test(), Test() };

会尝试复制 Test,这是无效的,因为它会尝试复制deque