std::array是否可以别名较大数组的片段
Can a std::array alias a fragment of a larger array?
假设我们有一个指针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));
您不仅取消了所有const
和volatile
资格,还取消了类型。请参阅以下答案:https://stackoverflow.com/a/103868/1621391。。。不加区分地丢弃cv
资格也可能导致UB。
其次,通过从一个不相关的类型投射的指针访问对象是未定义的行为。请参阅严格的混叠规则(感谢天顶)。因此,通过指针ay
的任何读或写访问都是未定义的。如果你非常幸运,代码应该会立即崩溃。如果它奏效了,邪恶的日子就在等着你。。。。
注意,std::array
不是也永远不会与任何不是std::array
的东西相同。
只是添加。。。在C++标准的工作草案中,它列出了明确的转换规则(你可以阅读它们)并有一个条款说明
5.4.3:以下未提及且未明确定义的任何类型转换用户([class.cov])格式不正确。
我建议你自己做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]; }
};
您还可以根据自己的喜好推出更多的成员函数/常量限定。但这有一些警告。。。指针必须已通过new T[len]
分配
因此,您可以在您的示例中使用它,如下所示:
auto ay = OwnedArray<decltype(*ptr)>::own_from(ptr, ptr_len);
该代码与没有什么不同
std::string str;
std::array<double,10>* arr = (std::array<double,10>*)(&str);
说明:标准不对std::array<T,n>
和T*
之间的任何兼容性提供任何保证。它根本不存在。也没有说std::array
是平凡型。如果没有这样的保证,T*
和std::array<T,n>
之间的任何转换都是未定义的行为,其规模与指向任何不相关类型的指针之间的转换相同。
我也看不出将已经构建的动态数组作为std::array
进行访问有什么好处。
p.S.常规免责声明。演员阵容本身总是百分之百的好。触发焰火的是结果指针的间接性,但为了简化起见,省略了这一部分。
我在这里回答第一个问题,因为第二个问题已经在其他答案中处理过了:
回顾:你。。。
具有指针CCD_ 18和CCD_
你问它是否。。。
是否可以像STL
array
一样访问它们?
答:这没有问题,但它的工作方式与您在代码示例中估计的不同:
std::array<T*, N> arr;
for(int i = 0; i<N; ++i)
{
arr[i] = ptr + i;
}
现在,您可以像使用原始指针一样使用数组元素。任何地方都没有未定义的行为。
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组的地址分配给变量并删除
- 从C++本机插件更新Vector3数组
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 数组索引的值没有增加
- 将对象数组的引用传递给函数
- 为char数组调整zlib-zpipe
- 2D数组来自文本输入,中间有空格
- std::向量与传递值的动态数组
- 在c++中用vector填充一个简单的动态数组
- 使用strcpy将char数组的元素复制到另一个数组
- 使用指针从C++中的数组中获取最大值
- C++使用整数的压缩数组初始化对象
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '