使用指针转换来存储/转换值:我打破了严格的别名规则吗



这个问题与这篇文章有关。

一些权威用户表示,以下代码违反了严格的别名规则。

#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;
    }
}

然而,我从来没有使用写入数据的指针,也从来没有共享指向它的指针,所以如果编译器没有意识到这一点,我就看不到变量中包含的值是如何变化的。我的印象是,也许我违反了一些规则,但不是严格的混叠规则。。。

注意:我不知道这有多重要,但我的编译器(gcc 4.9)不会发出警告。

*((U*) &data)如果是reinterpret_cast并且类型U不允许对类型T进行别名,则会违反严格别名。允许的类型显示在此列表中。

这条规则涉及阅读和写作。

这是一篇很好的文章,解释了规则背后的一些基本原理。

正如在主要的严格混叠线程中所指出的,您可以使用memcpy作为解决方案,例如:

U u;
memcpy( &u, &data, sizeof u );
return u;

在另一个功能中

memcpy( &data, &in, sizeof data );

请注意,类类型的原始字节副本受到一些限制(我认为类必须是POD,您最好确保它们具有相同的布局)。

然而,我从来没有使用写入数据的指针〔…〕

标准中的语言比这更通用[basic.life]/7有:

[…]一个指针指向原始对象、引用原始对象的引用或原始对象的名称对象[…]

operator=中,您使用类型为T的左值写入data,在operator U中,使用类型为U的指针读取它;其中CCD_ 11和CCD_。

只需使用memcpy。它保证能工作,而且效率很高(试试)!

最新更新