gpt4 book ai didi

c++ - 使用带有 unique_ptr 的 union

转载 作者:IT老高 更新时间:2023-10-28 22:34:18 31 4
gpt4 key购买 nike

当我尝试 std::move 或 std::make_unique 时,尝试在 union 中使用 unique_ptr 会给我一个段错误。

#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。所以我假设我在这里做错了什么。任何帮助将不胜感激。

编辑:

好的,所以分享我确定的代码可能是件好事。非常感谢所有指出我使用placement new 来管理变体成员中指针生命周期的人。

#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;
}

输出:

结构浮点 = 3.14

结构整数 = 739

结构有未分配的 union

结构浮点 = 8.95

结构整数 = 3

结构有未分配的 union

最佳答案

更改 union 的事件成员需要特别注意对象的生命周期。 C++ 标准说 (9.5p4):

Note: In general, one must use explicit destructor calls and placement new operators to change the active member of a union.

当成员是普通的旧数据时,它通常“正常工作”,即使您没有调用构造函数(使用放置 new)和析构函数。这是因为具有简单初始化的对象的生命周期开始于“获得足够大小和正确对齐的存储时”,而 union 提供了这一点。

现在您已经有了具有非平凡构造函数和析构函数的成员。它们的生命周期不会在获得存储时开始,您必须使初始化完成。这意味着放置新的。跳过析构函数调用也不安全,如果这些析构函数会产生程序所依赖的副作用(并且 unique_ptr 析构函数具有释放其目标的副作用),则会出现未定义的行为。

因此,您正在对生命周期尚未开始的成员调用移动赋值运算符。那是未定义的行为。

关于c++ - 使用带有 unique_ptr 的 union ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24713833/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com