假设类型A和类型B具有相同的大小,即sizeof(A) == sizeof(B)
,如何将包含B的某些内存重新解释为A?
我想做的是:
B myFunction()
{
A x;
// do some operations here.
// Solution 1: not working, since there is no such conversion function called 'B'.
// return B(x);
// Solution 2:
return *(B*)(&x); // should work.
}
似乎解决方案2正在运行。但是,如果要返回的实体不是上面x
之类的变量,而是一个函数......说,我有一个函数f2()
,如下所示:
A f2()
{
....
}
在myFunction()
中,我希望return语句使用f2()
:
return *(B*)(& (f2())); // definitely not working.
即。将f2()的返回值解释为类型B.
很明显,函数的返回值没有地址,因此不能使用地址运算符&
。
然后,我该怎么做?
答案 0 :(得分:3)
似乎解决方案2正在运作
根据类型A和B,它可能违反严格的别名规则。这是未定义的行为,但常见的结果是它在低优化级别下工作,在高级别的优化或使用不同的编译器时出错。
想象一下,将一把带有圆形腔室和安全装置的枪钉入腰带。是的,它还没有消失。爱好。
原因是两位工程师设计了两个相同功能的不同类,并在不同的代码中使用它
我认为,鉴于您提供的额外信息,如果A和B是两个标准布局类,同一数据成员的顺序相同,那么您就可以了。但请不要引用我,请自行检查标准。
在任何情况下,如果你不想触及这两个类,通常的做法就是定义一个函数从一个函数转换为另一个函数:
B A_to_B(const A &a) {
B b{a.thiss, a.thatt, a.the_otherr};
return b;
}
使这个函数成为A的friend
,如果证明有必要,不应该破坏任何东西。当然,如果A有私人数据成员,那么你的地位很难以假设你不允许知道的这些数据不仅存在,而且与B的布局相同。
如何将包含A的内存重新解释为B?
A x = f2();
B result;
std::memcpy(&result, &x, sizeof result);
return result;
此代码避免违反严格的别名规则,但如果您的实现中存在类型B的陷阱表示,则可能会导致未定义的行为。但这是不可避免的:如果您开始使用的值不是您想要读取的类型的有效位模式,则无法通过任何方式进行类型惩罚。此外,如果类型B具有非平凡的构造函数和/或析构函数,那么您就会遇到麻烦,除了允许B的正确生命周期发生之外,可能无法解决这个问题。
答案 1 :(得分:1)
关于使用union的更详细的答案: 您可以尝试联合a和b:
union AB
{
A a;
B b;
};
当您使用这两个功能时,请使用AB:
A f2()
{
....
}
B myFunction()
{
AB x;
x.a = f2();
return x.b;
}
答案 2 :(得分:0)
上帝是丑陋的......但是好的(我希望这个问题只是学术问题而不是真正代码的一部分)
A a;
B b;
memcpy(&b,&a,sizeof(B))
如果使用指针则更容易,但因为按值返回,所以首先需要内存。并且您不能使用任何赋值,因为它会使用复制/赋值构造函数,这可能会弄乱类中的内容(两个复制构造函数中的哪些将被使用等)