将“this”指针强制转换为另一种类型并不违反严格的别名?

时间:2014-01-11 09:06:35

标签: c++ templates pointers c++11 strict-aliasing

所以,如果我做这样的事情:

#include <ios>

using std::forward;

template<class T>
struct pod_version final{
    private:
        alignas(T) uint8_t m_data[sizeof(T)];
    public:
        pod_version()=default;
        pod_version(const pod_version&)=default;
        pod_version(pod_version&&)=default;
        ~pod_version()=default;
        pod_version& operator=(const pod_version&)=default;
        pod_version& operator=(pod_version&&)=default;

        template<class...V>void construct(V&&...v){
            new (m_data) T(forward<V>(v)...);
        }

        void destroy(){
            reinterpret_cast<T*>(m_data)->~T(); // g++: warning typed punned blah im allowed to break ur code LOL
            reinterpret_cast<T*>(this)->~T(); // g++: :D
        }
};

int main(){
    pod_version<int> x;
    x.construct(5);
    x.destroy();
    return 0;
}

注意:“m_data”和“this”应该指向同一个地方......

gcc 4.8.1

3 个答案:

答案 0 :(得分:1)

使用char,而不是uint8_t

类型处罚规则对charsigned charunsigned char有特殊情况,并且只有这些类型。 uint8_t不一定要指其中一个。

请注意,此pod_version类的整个概念是可疑的。您正在强制它们无效的类型上的普通复制语义。您的代码将尝试在未初始化的内存或对象的二进制映像上调用析构函数。两者都会导致未定义的行为。

答案 1 :(得分:0)

您的编译器正确投诉m_data,因为m_data不是char*类型,而是类型int8_t*。除了char*unsigned char*signed char*之外,严格的别名规则不允许进行任何类型的惩罚。

可能,编译器无法通过将pod_version<T>*转换为T*来确定可能暗示某些恶意。毕竟这些是复杂的类型,并且编译器不知道您要访问的T的哪个成员,它可能是int8_t成员,在这种情况下,强制转换就完全可以了。毕竟,仅当您访问与不同基本类型相同的内存位置时,才会调用未定义的行为,而不是在更改指针类型时。

在任何情况下,你通过编写演员来明确告诉编译器“我知道我在做什么”,所以任何完整性检查都是纯粹可选的。

答案 2 :(得分:0)

标准不要求警告。实施可能会以任何理由警告您,无论他们认为合适,或者根本不会。

为了它的价值,gcc 4.8.2用-Wall静默编译你的代码。编辑:不,它没有。