使用指向 store/cast 值的指针转换:我是否违反了严格的别名规则?
Using pointer conversions to store/cast values: Am I breaking the strict aliasing rule?
问题涉及。
一些权威用户表示以下代码中断strict aliasing rules。
#include <boost/static_assert.hpp>
template <typename T>
struct MyType {
private:
T data;
public:
template <typename U>
operator U () {
BOOST_STATIC_ASSERT_MSG(sizeof(U) == sizeof(T),"Trying to convert to data type of different size");
return *((U*) &data);
}
template <typename U>
NeonVectorType<T>& operator =(const U& in) {
BOOST_STATIC_ASSERT_MSG(sizeof(U) == sizeof(T),"Trying to copy from data type of different size");
data = *((T*) &in);
return *this;
}
}
但是,我从不使用指向 write 数据的指针,而且我从不共享指向它的指针,所以我看不出变量中包含的值如何在没有的情况下发生变化编译器意识到这正在发生。我的印象是,也许我违反了一些规则,但不是严格的别名...
注意:我不知道这有多重要,但我的编译器 (gcc 4.9) 不会发出警告。
*((U*) &data)
如果这是 reinterpret_cast
并且类型 U
不允许作为类型 T
的别名,则将违反严格别名。允许的类型出现在 this list.
中
规则参考.
Here 是一篇很好的文章,解释了规则背后的一些基本原理。
正如主严格别名线程中所述,您可以使用 memcpy
作为解决方法,例如:
U u;
memcpy( &u, &data, sizeof u );
return u;
在另一个函数中
memcpy( &data, &in, sizeof data );
注意 class 类型的原始字节副本受到一些限制(我认为 classes 必须是 POD,你最好确保它们具有相同的布局) .
However, I am never using a pointer to write data [...]
标准中的语言比这个更通用; [basic.life]/7 有:
[...] a pointer that
pointed to the original object, a reference that referred to the original object, or the name of the original
object [...]
在您的 operator=
中,您使用类型 T
的左值写入 data
,而在 operator U
中,您使用类型指针 U
阅读它;其中 U
和 T
不相关且与字符类型无关,这是 UB。
只需使用memcpy
。它保证有效,而且高效(尝试一下)!
问题涉及
一些权威用户表示以下代码中断strict aliasing rules。
#include <boost/static_assert.hpp>
template <typename T>
struct MyType {
private:
T data;
public:
template <typename U>
operator U () {
BOOST_STATIC_ASSERT_MSG(sizeof(U) == sizeof(T),"Trying to convert to data type of different size");
return *((U*) &data);
}
template <typename U>
NeonVectorType<T>& operator =(const U& in) {
BOOST_STATIC_ASSERT_MSG(sizeof(U) == sizeof(T),"Trying to copy from data type of different size");
data = *((T*) &in);
return *this;
}
}
但是,我从不使用指向 write 数据的指针,而且我从不共享指向它的指针,所以我看不出变量中包含的值如何在没有的情况下发生变化编译器意识到这正在发生。我的印象是,也许我违反了一些规则,但不是严格的别名...
注意:我不知道这有多重要,但我的编译器 (gcc 4.9) 不会发出警告。
*((U*) &data)
如果这是 reinterpret_cast
并且类型 U
不允许作为类型 T
的别名,则将违反严格别名。允许的类型出现在 this list.
规则参考
Here 是一篇很好的文章,解释了规则背后的一些基本原理。
正如主严格别名线程中所述,您可以使用 memcpy
作为解决方法,例如:
U u;
memcpy( &u, &data, sizeof u );
return u;
在另一个函数中
memcpy( &data, &in, sizeof data );
注意 class 类型的原始字节副本受到一些限制(我认为 classes 必须是 POD,你最好确保它们具有相同的布局) .
However, I am never using a pointer to write data [...]
标准中的语言比这个更通用; [basic.life]/7 有:
[...] a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object [...]
在您的 operator=
中,您使用类型 T
的左值写入 data
,而在 operator U
中,您使用类型指针 U
阅读它;其中 U
和 T
不相关且与字符类型无关,这是 UB。
只需使用memcpy
。它保证有效,而且高效(尝试一下)!