真的很简单的问题。以下示例代码中发生了什么导致它无法编译?
错误发生在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
答案 0 :(得分:3)
从C ++ 11开始,拥有一个只有默认可构造对象的容器是完全合法的,前提是你不要使用任何需要对象可复制或移动的操作。
但是,std::initializer_list
仅允许const
访问其元素,这意味着您无法移动它们。因此
vector<Test> v = { Test(), Test() };
会尝试复制 Test
,这是无效的,因为它会尝试复制deque
。