用作对象的封装char数组是否违反严格的别名规则 [英] Does encapsulated char array used as object breaks strict aliasing rule

查看:137
本文介绍了用作对象的封装char数组是否违反严格的别名规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下类别是否违反严格的别名规则:

Do the following class break the strict aliasing rule:

template<typename T>
class store {
    char m_data[sizeof(T)];
    bool m_init;
public:
    store() : m_init(false) {}
    store(const T &t) : init(true) {
        new(m_data) T(t);
    }
    ~store() {
        if(m_init) {
            get()->~T();
        }
    }
    store &operator=(const store &s) {
        if(m_init) {
            get()->~T();
        }
        if(s.m_init) {
            new(m_data) T(*s.get());
        }
        m_init = s.m_init;
    }
    T *get() {
        if (m_init) {
            return reinterpret_cast<T *>(m_data);
        } else {
            return NULL;
        }
    }
}

我对标准的理解是,它是不正确的,但我不确定(我的用法是拥有对象数组T +这些对象的一些元数据,但可以控制对象的构造/分解,而无需手动分配内存),因为分配的对象用作标准位置new的示例.

My reading of a standard is that it is incorrect but I am not sure (my usage is to have an array of objects T + some metadata of those objects but to have control over the object construction/deconstruction without manually allocating memory) as the allocated objects are used as examples for placement new in standard.

推荐答案

标准包含以下注释:

[注意:一种典型的实现方式是将alignment_storage定义为:

[ Note: A typical implementation would define aligned_storage as:

template <std::size_t Len, std::size_t Alignment>
struct aligned_storage {
  typedef struct {
    alignas(Alignment) unsigned char __data[Len];
  } type;
};

尾注]

              b&b ;              nbsp; b ;                [n] pt指针. 20.9.7.5/1

                                                                   — Pointer modifications [meta.trans.ptr] 20.9.7.5/1

aligned_storage部分定义为:

And aligned_storage is defined in part with:

成员typedef type 应该是POD类型,适合用作大小最大为 Len 并且对齐方式为对齐.

The member typedef type shall be a POD type suitable for use as uninitialized storage for any object whose size is at most Len and whose alignment is a divisor of Align.

该标准涵盖的唯一限制可以构造对象的地址的属性是对齐.一个实现可能还有其他一些限制,但是我对任何限制都不熟悉.因此,只需确保正确的对齐就足以实现您的实现,我认为这应该可以. (在C ++ 11之前的编译器中,您可以使用编译器扩展名来设置对齐方式,例如__attribute__((alignment(X)))__declspec(align(X)).

The only property covered by the standard that restricts the addresses at which an object can be constructed is alignment. An implementation might have some other restrictions, however I'm not familiar with any that do. So just ensure that having correct alignment is enough on your implementation and I think this should be okay. (and in pre-C++11 compilers you can use use compiler extensions for setting alignment such as __attribute__((alignment(X))) or __declspec(align(X)).

我相信,只要您不直接访问基础存储,别名规则甚至都不会出现在图片中,因为别名规则涵盖了何时可以通过的对象访问对象的值不同的类型.构造一个对象并仅访问该对象并不涉及通过任何其他类型的对象访问该对象的值.

I believe that as long as you don't access the underlying storage directly the aliasing rules don't even come into the picture, because the aliasing rules cover when it is okay to access the value of an object through an object of a different type. Constructing an object and accessing only that object doesn't involve accessing the object's value through an object of any other type.

别名规则专门允许char数组对其他对象进行别名.

The aliasing rules specifically allow char arrays to alias other objects.

如果程序尝试通过以下方式访问对象的存储值 除以下类型之一以外的glvalue的行为是 未定义:

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

[...]

-字符或无符号字符类型.

— a char or unsigned char type.

              b&b ;              nbsp; b ; s< bass;< bass;         s s s s< bass' r值[val]值3的L值./10

                                                                   — Lvalues and rvalues [basic.lval] 3.10/10

您确实需要确保数组针对T类型正确对齐.

You do need to make sure that the array is properly aligned for type T though.

alignas(T) char m_data[sizeof(T)];

以上是用于设置对齐方式的C ++ 11语法,但是如果您使用的是C ++ 03编译器,则需要特定于编译器的属性来执行相同的操作. GCC具有__attribute__((aligned(32))),MSVC具有__declspec(align(32))

The above is C++11 syntax for setting alignment, but if you're on a C++03 compiler then you'll need a compiler specific attribute to do the same thing. GCC has __attribute__((aligned(32))) and MSVC has __declspec(align(32))

Kerrek SB提出了一个很好的观点,即别名规则表明可以通过char数组访问T对象的值是可以的,但这并不意味着可以通过T对象访问char数组的值是可以的.但是,如果放置新表达式的定义正确,则将创建一个T对象,我认为可以按定义将其作为T对象进行访问,并且读取原始char数组将访问创建的T对象的值,该内容已在以下内容中进行了介绍.别名规则.

Kerrek SB brings up a good point that the aliasing rules state that it's okay to access the value of a T object via a char array, but that may not mean that accessing the value of a char array via a T object is okay. However, if the placement new expression is well defined then that creates a T object which I think it's okay to accesses as a T object by definition, and reading the original char array is accessing the value of the created T object, which is covered under the aliasing rules.

我认为这意味着您可以将T对象存储在例如int数组中,并且只要您不通过原始int数组访问该T对象的值,就不会遇到未定义的情况行为.

I think that implies that you could store a T object in, for example, an int array, and as long as you don't access the value of that T object through the original int array then you're not hitting undefined behavior.

这篇关于用作对象的封装char数组是否违反严格的别名规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆