C++创建具有可变项目数的结构的方法
C++ way of creating a structure with variable number of items
我需要创建一个内存区域,最后有可变数量的项目。我可以这样写的东西:
#pragma pack(push,0)
struct MyData
{
int noOfItems;
int buffer[0];
};
#pragma pack(pop)
MyData * getData(int size)
{
bufferSize = size* sizeof(int) + sizeof(MyData ::noOfItems);
MyData * myData= (MyData *)new char[m_bufferSize];
return myData;
}
此代码适用于VS 2015,并警告大小为零的数组不是标准的
一些搜索告诉我这是一个 C hack,C++不支持。
大小为 0 的数组
零长度数组
如果我在 C/C++ 中定义一个 0 大小的数组会发生什么?
我怎样才能在C++中做到这一点
这样的事情呢?它适用于普通可复制的类型:
template <typename T, typename INT = size_t>
class packed_array {
public:
packed_array(INT size) {
buf_ = new char[sizeof(INT) + size * sizeof(T)];
memcpy(buf_, &size, sizeof(INT));
}
~packed_array() { delete[] buf_; }
void set(INT index, T val) {
memcpy(buf_ + sizeof(INT) + index * sizeof(T), &val, sizeof(T));
}
T get(INT index) const {
T temp;
memcpy(&temp, buf_ + sizeof(INT) + index * sizeof(T), sizeof(T));
return temp;
}
const char* data() const { return buf_; }
private:
char* buf_;
static_assert(std::is_trivially_copyable<T>::value);
};
int main() {
int n;
std::cin >> n;
packed_array<double, int> a(n);
for (int i = 0; i < n; i++)
a.set(i, pow(2.0, i));
for (int i = 0; i < n; i++)
std::cout << a.get(i) << std::endl;
}
现场演示:https://wandbox.org/permlink/Vc4ok756R1Sxieoj
template<class T, class D>
struct var_array_at_end {
var_array_at_end( std::size_t N ) {
::new( (void*)data() ) std::aligned_storage_t<sizeof(T)*N, alignof(T)>;
for (std::size_t i = 0; i < N; ++i) {
::new( (void*)( data()+sizeof(T)*i) ) ) T();
}
}
char* data() { return reinterpret_cast<char*>(this)+sizeof(D); }
char const* data() const { return reinterpret_cast<char*>(this)+sizeof(D); }
T* ptr(std::size_t i = 0) { return reinterpret_cast<T*>( data()+sizeof(T)*i ); }
T const* ptr(std::size_t i = 0) const { return reinterpret_cast<T*>( data()+sizeof(T)*i ); }
T& operator[](std::size_t n) {
return *ptr(n);
}
T const& operator[](std::size_t n) const {
return *ptr(n);
}
};
struct MyData:
var_array_at_end<int, MyData>
{
private:
explicit MyData( int count ):
var_array_at_end<int, MyData>( count>0?(unsigned)count:0 ),
noOfItems(count)
{}
struct cleanup {
void operator()(MyData* ptr) {
char* buff = reinterpret_cast<char*>(ptr);
ptr->~MyData();
delete[] buff;
}
};
public:
using up = std::unique_ptr<MyData*, cleanup>;
static up create( int count ) {
if (count < 0) count = 0;
std::unique_ptr<char> buff = std::make_unique<char[]>( sizeof(MyData)+sizeof(int)*count );
auto* ptr = ::new( (void*)buff.get() ) MyData( count );
(void)buff.release();
return up( ptr, {} );
}
int noOfItems;
};
MyData * getData(int size)
{
return MyData::create(size).release(); // dangerous, unmanaged memory
}
我相信这是符合标准的,假设您的实现不会在琐碎类型(如 char(的数组上添加填充。 我不知道有任何实现可以做到这一点。
我不认为MyData
只包含普通的旧数据;你可以用上面的内容在其中塞进一个std::vector
。 我也许可以用这个假设简化几行。
这不仅仅是一点点痛苦。
auto foo = MyData::create(100)
创建一个唯一的 ptr 来MyData
,其后有 100int
秒的缓冲区。(*foo)[77]
访问缓冲区的第 77 个元素。
由于标准中的缺陷,MyData
之后没有数组,而是在相邻内存位置中包含 100 个不同int
对象的缓冲区。 这两件事之间存在非常烦人的差异;朴素指针算术保证在数组中工作,但不能在缓冲区中打包的相邻int
S 之间工作。 我不知道有编译器强制执行这种差异。
相关文章:
- 如何循环打印顶点结构
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 预处理器:插入结构名称中的前一个行号
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 孤立代码块在结构中引发异常
- 有什么方法可以遍历结构吗
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 无法将结构注册为增强几何体3D点
- 多成员Constexpr结构初始化
- C++将文本文件中的数据读取到结构数组中
- 如何重构类层次结构以避免菱形问题
- 如何在C++中序列化结构数据
- std::vector的包装器,使数组的结构看起来像结构的数组
- 没有为自己的结构调用列表推回方法
- 奇怪的结构&GCC&clang(void*返回类型)
- 在 c++ 中拥有一组结构的正确方法是什么?
- vscode g++链路故障:体系结构x86_64的未定义符号
- C++创建具有可变项目数的结构的方法