gpt4 book ai didi

c++ - union 内结构的重载类型转换运算符问题

转载 作者:行者123 更新时间:2023-11-30 04:47:26 24 4
gpt4 key购买 nike

我正在尝试将一个简单的 vector 调配功能作为一个宠物项目来实现,以进入模板元编程。在开源数学库 glm 和其他一些关于 SO 的帖子的帮助下,我想出了一个解决方案,它基本上可以工作但有一个错误。

我已经实现了几个结构,这些结构包含表示二维欧几里得 vector 所需的数据。结构“vec2”有一个 union ,它包含一个包含两个元素的 float 组(float data[2])和两个结构“scalarSwizzle”的实例,它应该实现混合机制,允许我像 vec 一样访问 vector 。 data[0] 左右 vec.x.

按照我目前实现的代码:

    #include <iostream>

template<typename T>
void print(T value)
{
std::cout << "print func: " << value << std::endl;
}

template<typename T, unsigned int I>
struct scalarSwiz
{
T value[1];

T &operator=(const T newValue)
{
value[I] = newValue;
return value[I];
}

operator T()
{
return value[I];
}
};


template<typename T>
struct vec2
{
union
{
T data[2];
scalarSwiz<T, 0> x;
scalarSwiz<T, 1> y;
};

vec2()
{
x = 0.0f;
y = 1.0f;
}

vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};


int main(int argc, char *args[])
{
vec2<float> vec1{5.0f, 1.0f};

std::cout << "value vec1.data[0]: " << vec1.data[0] << std::endl;
std::cout << "value vec1.data[1]: " << vec1.data[1] << std::endl;
std::cout << "value vec1.x: " << vec1.x << std::endl;
std::cout << "value vec1.y: " << vec1.y << std::endl << std::endl;

print(vec1.data[0]);
print(vec1.data[1]);
print(vec1.x);
print(vec1.y);

std::cin.get();

}

输出如下:

value vec1.data[0]: 5
value vec1.data[1]: 567.4
value vec1.x: 5
value vec1.y: 567.4

print func: 5
print func: 567.4
print func: 5
print func: 2.5565e-39

我希望直接在 main() 中和通过 print() 打印值的输出是相同的,但是当我通过 print() 函数打印它时 vec.y 没有解析。所以我猜想“scalarSwizzle”中的重载类型转换运算符有问题,但我不知道是什么。我也不明白的是,为什么 visual studio 也没有正确解析值,如下图所示:

Visual Studio Debugger

vec1.y 似乎指向与 vec.x 相同的物理地址,而 main() 中的直接 std::cout 工作正常。

我已经尝试了几天来解决这个问题,为什么重载的类型转换运算符对 vec.y 不起作用,但我就是不明白。也许这里有人可以帮助我解决这个问题。

谢谢!

最佳答案

首先

template<typename T, unsigned int I>
struct scalarSwiz
{
T value[1];

T &operator=(const T newValue)
{
value[I] = newValue;
return value[I];
}

operator T()
{
return value[I];
}
};

如果 I != 0(数组访问越界)会导致未定义的行为,所以不要指望您的代码是正确的甚至是稳定的。

其次,访问 union 体的非事件成员也是未定义的行为(根据 c++ 标准)。但是,msvc、gcc 和 clang 扩展了 c++ 标准,因此访问非事件成员的行为就像我们期望的那样。

最后,您的 scalarSwiz 类型可以用匿名结构替换:

template<typename T>
struct vec2
{
union
{
T data[2];
struct
{
T x, y;
};
};

vec2()
{
x = 0.0f;
y = 1.0f;
}

vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};

关于您的 Visual Studio 调试器显示:这是因为您的 scalarSwiz 定义。您定义了一个长度为 1 T value[1] 的数组,并将 2 个 scalarSwiz 对象放在一个 union 中。因为 union 的每个成员都共享相同的内存(或者更确切地说,从相同的内存位置开始),所以您的两个 value 成员都指向 data 数组的开头。监 window 口仅显示特定类型的成员及其值,它不知道您的古怪索引。并且因为两个数组占用相同的内存,所以显示相同的值。

关于c++ - union 内结构的重载类型转换运算符问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56237000/

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