c++ - 调用显式转换构造函数的 C 风格转换是否正确?

标签 c++ compiler-construction standards

C 风格的转换能否调用显式转换构造函数?

考虑以下代码:

class Vec3
{
public:

    explicit Vec3(float All) 
        : X(All), Y(All), Z(All)
    {
    }

    Vec3(float InX, float InY, float InZ)
        : X(InX), Y(InY), Z(InZ)
    {
    }

    Vec3()
        : X(0), Y(0), Z(0)
    {
    }

    float X, Y, Z;
};

void Morph(const Vec3& In, Vec3& Out)
{
    Out = In;
}

int main(void)
{
    float Array[3] = {1.0f, 2.0f, 3.0f};
    Vec3 Morphed;
    Morph((const Vec3&)Array[0], Morphed);
}

在 Microsoft VS2010 的编译器上,它将 (const Vec3&)Array[0] 行转换为 reinterpret_cast 和复制构造函数,以将参数传递给函数。 Morphed 的值为 [1.0f, 2.0f, 3.0f]。

在第三方的另一个编译器上,它将 (const Vec3&)Array[0] 转换为对 explicit Vec3(float) 的调用,然后将复制构造函数转换为将参数传递给函数。 Morphed 的值为 [1.0f, 1.0f, 1.0f]。

我通过查看两个编译器的反汇编验证了这一点:

VS2010:

   483:     float Array[3] = {1.0f, 2.0f, 3.0f};
0000000143E68049  movss       xmm0,dword ptr [__real@3f800000 (145DA1F18h)]  
0000000143E68051  movss       dword ptr [rsp+28h],xmm0  
0000000143E68057  movss       xmm0,dword ptr [__real@40000000 (145DC9704h)]  
0000000143E6805F  movss       dword ptr [rsp+2Ch],xmm0  
0000000143E68065  movss       xmm0,dword ptr [__real@40400000 (145DC9708h)]  
0000000143E6806D  movss       dword ptr [rsp+30h],xmm0  
   484:     Vec3 Morphed;
0000000143E68073  xorps       xmm0,xmm0  
0000000143E68076  movss       dword ptr [rsp+58h],xmm0  
0000000143E6807C  xorps       xmm0,xmm0  
0000000143E6807F  movss       dword ptr [rsp+5Ch],xmm0  
0000000143E68085  xorps       xmm0,xmm0  
0000000143E68088  movss       dword ptr [rsp+60h],xmm0  
   485:     Morph((const Vec3&)Array[0], Morphed);
0000000143E6808E  lea         rdx,[rsp+58h]  
0000000143E68093  lea         rcx,[rsp+28h]  
0000000143E68098  call        Morph (143E67FB0h) 

其他编译器:

   184:     float Array[3] {1.0f, 2.0f, 3.0f};
0000000001E1F3B0  mov          rax,qword ptr [000000000432D1B0h] 
0000000001E1F3B7  mov          qword ptr [rbp-14h],rax 
0000000001E1F3BB  mov          edi,dword ptr [000000000432D1B8h] 
0000000001E1F3C1  mov          dword ptr [rbp-0Ch],edi 
   185:     Vec3 Morphed;
0000000001E1F3C4  lea          rdi,[rbp-130h] 
0000000001E1F3CB  call         Vec3::Vec3() (0000000003C119C0h) 
   186:     Morph((const Vec3&)Array[0], Morphed);
0000000001E1F3D0  lea          rdi,[rbp-140h] 
0000000001E1F3D7  vmovss       xmm0,dword ptr [rbp-14h] 
0000000001E1F3DC  call         Vec3::Vec3(float) (0000000003C119E0h) 
0000000001E1F3E1  lea          rdi,[rbp-140h] 
0000000001E1F3E8  lea          rsi,[rbp-130h] 
0000000001E1F3EF  call         Morph(Vec3 const&,Vec3&) (0000000001E1F350h) 

不用说,这会导致很多问题。哪个编译器是正确的?第三方代码依赖于微软的实现,但我们正在使用不同平台的不同编译器进行编译。

最佳答案

就 C++ 标准而言,将 float & 转换为 const Vec3 & 是未定义的行为。两种编译器都是正确的,因为代码不受 C++ 的保护。

如果您希望这是一个 protected 转换,您必须停止类型双关并将 float 数组真正复制到 Vec3.

关于c++ - 调用显式转换构造函数的 C 风格转换是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18543090/

相关文章:

c++ - 如何计算一个点(高维空间)相对于由一组点形成的超平面的对称性?

c++ - 自动将进入/退出功能日志添加到项目中

Eclipse 显示注释错误但构建成功

java - Struts2-Full-Hibernate 插件是集成 Struts2 和 Hibernate 的标准方式吗?

c++ - 我的 bst 实现有什么问题吗?

c++ - 聚合引用成员和临时生命周期

c# - TargetedPatchingOptOut : "Performance critical to inline across NGen image boundaries"?

c++ - 在 C++ 中隐藏 int 变量的名称

standards - 我怎样才能跟上最新的 Web 开发标准?

c++ - 在 C++/Qt 中定义纯虚拟信号是否有效?