类型转换函数的返回值为相同大小的无关类型

时间:2016-09-01 08:19:33

标签: c++

假设类型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.

很明显,函数的返回值没有地址,因此不能使用地址运算符&

然后,我该怎么做?

3 个答案:

答案 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))

如果使用指针则更容易,但因为按值返回,所以首先需要内存。并且您不能使用任何赋值,因为它会使用复制/赋值构造函数,这可能会弄乱类中的内容(两个复制构造函数中的哪些将被使用等)