尝试在工会中使用unique_ptr时,当我尝试std :: move或std :: make_unique时,会给我一个segfault.
#include <iostream> #include <memory> union myUnion{ struct{std::unique_ptr<float> upFloat;}structUpFloat; struct{std::unique_ptr<int> upInt;}structUpInt; myUnion(){} ~myUnion(){} }; struct myStruct{ int x; myUnion num; }; int main() { myStruct aStruct,bStruct; aStruct.x = 1; bStruct.x = 2; auto upF = std::make_unique<float>(3.14); auto upI = std::make_unique<int>(3); aStruct.num.structUpFloat.upFloat = std::move(upF); bStruct.num.structUpInt.upInt = std::move(upI); std::cout << "aStruct float = " << *aStruct.num.structUpFloat.upFloat << std::endl; std::cout << "bStruct int = " << *bStruct.num.structUpInt.upInt << std::endl; return 0; }
但是,使用正常指针可以按预期方式工作:
#include <iostream> #include <memory> union myUnion{ struct{float *pFloat;}structPFloat; struct{int *pInt;}structPInt; myUnion(){} ~myUnion(){} }; struct myStruct{ int x; myUnion num; }; int main() { myStruct aStruct,bStruct; aStruct.x = 1; bStruct.x = 2; auto upF = std::make_unique<float>(3.14); auto upI = std::make_unique<int>(3); aStruct.num.structPFloat.pFloat = upF.get(); bStruct.num.structPInt.pInt = upI.get(); std::cout << "aStruct float = " << *aStruct.num.structPFloat.pFloat << std::endl; std::cout << "bStruct int = " << *bStruct.num.structPInt.pInt << std::endl; return 0; }
这是使用clang.3.4.2或gcc.4.9.0.所以我假设我在这里做错了.任何帮助将不胜感激.
编辑:
好的,所以分享我定下的代码可能是一件好事.非常感谢所有指出我使用新版本管理变体成员中我的指针的生命的人.
#include <memory> #include <iostream> #include <vector> struct myStruct { public: union { std::unique_ptr<float> upFloat; std::unique_ptr<int> upInt; }; enum class unionType {f,i,none} type = unionType::none; // Keep it sane myStruct(){} myStruct(std::unique_ptr<float> p) { new (&upFloat) std::unique_ptr<float>{std::move(p)}; type = unionType::f; } myStruct(std::unique_ptr<int> p) { new (&upInt) std::unique_ptr<int>{std::move(p)}; type = unionType::i; } ~myStruct() { switch (type) { case unionType::f: upFloat.~unique_ptr<float>(); break; case unionType::i: upInt.~unique_ptr<int>(); break; } } }; int main() { std::vector<std::unique_ptr<myStruct>> structVec; structVec.push_back(std::make_unique<myStruct>(std::make_unique<float>(3.14f))); structVec.push_back(std::make_unique<myStruct>(std::make_unique<int>(739))); structVec.push_back(std::make_unique<myStruct>()); structVec.push_back(std::make_unique<myStruct>(std::make_unique<float>(8.95f))); structVec.push_back(std::make_unique<myStruct>(std::make_unique<int>(3))); structVec.push_back(std::make_unique<myStruct>()); for(auto &a: structVec) { if(a->type == myStruct::unionType::none) { std::cout << "Struct Has Unallocated Union" << std::endl; } else if(a->type == myStruct::unionType::f) { std::cout << "Struct float = " << *a->upFloat << std::endl; } else { std::cout << "Struct int = " << *a->upInt << std::endl; } std::cout << std::endl; } return 0; }
输出:
Struct float = 3.14
Struct int = 739
结构有未分配联盟
Struct float = 8.95
Struct int = 3
结构有未分配联盟
解决方法
对于无限制的联盟,你必须管理自己一些构造/破坏.
以下可能有帮助:
union myUnion{ std::unique_ptr<float> upFloat; std::unique_ptr<int> upInt; myUnion(){ new (&upFloat) std::unique_ptr<float>{};} ~myUnion() {} }; class myStruct { public: ~myStruct() { destroy(); } void destroy() { switch (type) { case unionType::f: num.upFloat.~unique_ptr<float>(); break; case unionType::i: num.upInt.~unique_ptr<int>(); break; } } void set(std::unique_ptr<int> p) { destroy(); new (&num.upInt) std::unique_ptr<int>{std::move(p)}; type = unionType::i; } void set(std::unique_ptr<float> p) { destroy(); new (&num.upFloat) std::unique_ptr<float>{std::move(p)}; type = unionType::f; } public: enum class unionType {f,i} type = unionType::f; // match the default constructor of enum myUnion num; }; int main() { myStruct aStruct,bStruct; aStruct.set(std::make_unique<float>(3.14f)); bStruct.set(std::make_unique<int>(3)); std::cout << "aStruct float = " << *aStruct.num.upFloat << std::endl; std::cout << "bStruct int = " << *bStruct.num.upInt << std::endl; return 0; }