c++ - std::array 可以别名更大数组的片段吗?

标签 c++ arrays c++11 strict-aliasing type-punning

假设我们有一个指针 T* ptr;ptr, ptr+1, … ptr+(n-1) 都引用有效的 T 类型对象。

是否可以像访问 STL array 一样访问它们?或者执行以下代码:

std::array<T,n>* ay = (std::array<T,n>*) ptr

调用未定义的行为?

最佳答案

是的,它是一个未定义的行为,一个经典的...

首先,了解你刚刚做了什么:

std::array<T,n>* ay = (std::array<T,n>*) ptr

可以翻译为:

using Arr = std::array<T,n>;
std::array<T,n>* ay = reinterpret_cast<Arr*>( const_cast<TypeOfPtr>(ptr));

您不仅抛弃了所有 constvolatile 限定条件,而且还转换了类型。看到这个答案:https://stackoverflow.com/a/103868/1621391 ...不加选择地放弃 cv 资格也可能导致 UB。

其次,通过从不相关类型强制转换的指针访问对象是未定义的行为。参见 the strict aliasing rule (感谢天顶)。因此,通过指针 ay 进行的任何读取或写入访问都是未定义的。如果您非常幸运,代码应该会立即崩溃。如果它有效,邪恶的日子就在等着你....

请注意 std::array不是也永远不会与不是 std::array 的任何事物相同.

只是添加... 在 working draft of the C++ standard , 它列出了 out explicit conversion rules . (你可以阅读它们) 并且有一个子句说明

.....

5.4.3: Any type conversion not mentioned below and not explicitly defined by the user ([class.conv]) is ill-formed.

.....


我建议你自己做饭array_view (希望在 C++17 中出现)。这真的很容易。或者,如果您想要一些所有权,您可以像这样制作一个简单的所有权:

template<typename T>
class OwnedArray{
    T* data_ = nullptr;
    std::size_t sz = 0;
    OwnedArray(T* ptr, std::size_t len) : data_(ptr), sz(len) {}
public:
    static OwnedArray own_from(T* ptr, std::size_t len)
    { return OwnedArray(ptr, len);  }

    OwnedArray(){}

    OwnedArray(OwnedArray&& o)
    { data_ = o.data_; sz = o.sz; o.data_=nullptr; o.sz=0; }

    OwnedArray& operator = (OwnedArray&& o)
    { delete[] data_; data_ = o.data_; sz = o.sz; o.data_=nullptr; o.sz=0; }

    OwnedArray(const OwnedArray& o) = delete;

    OwnedArray& operator = (const OwnedArray& o) = delete;    

    ~OwnedArray(){ delete[] data_; }

    std::size_t size() const { return sz; }

    T* data() return { data_; }

    T& operator[] (std::size_t idx) { return data_[idx]; }
};

...您可以根据需要推出更多成员函数/const 限定条件。但这有一些警告......必须通过 new T[len]

分配指针

因此您可以像这样在示例中使用它:

auto ay = OwnedArray<decltype(*ptr)>::own_from(ptr, ptr_len);

关于c++ - std::array 可以别名更大数组的片段吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36508995/

相关文章:

c++ - 如何从阻塞上下文访问基于类的参与者的状态(C++ 参与者框架)

C++ “was not declared in this scope” 编译错误

arrays - ruby 优雅地将一组项目包装到一个对象中

c++ - auto-complete-clang-async 无法按预期在 Emacs 上运行

c++ - c++ 11中的 future vector

c++ - 默认d'tor是否足以用于复数 vector ?

c++ - 这是有效的 C 代码吗?

ios - 快速从对象数组中删除对象

php - 数组是空的,但它一直认为里面有东西

c++ - 类型别名中的详细类型说明符