这是在C++中制作可变大小结构的最佳方法吗?我不想使用vector,因为初始化后长度不会改变.
struct Packet { unsigned int bytelength; unsigned int data[]; }; Packet* CreatePacket(unsigned int length) { Packet *output = (Packet*) malloc((length+1)*sizeof(unsigned int)); output->bytelength = length; return output; }
编辑:重命名变量名称和更改的代码更正确.
关于你在做什么的一些想法:
使用C风格的可变长度struct idiom允许您为每个数据包执行一次免费存储分配,这是struct Packet
包含a时所需数量的一半std::vector
.如果您分配一个非常大的数量的数据包,然后进行一半的自由存储分配/释放操作很可能是显著.如果您还在进行网络访问,那么等待网络所花费的时间可能会更加重要.
该结构表示数据包.您是否计划直接从套接字读取/写入struct Packet
?如果是这样,您可能需要考虑字节顺序.您在发送数据包时是否必须从主机转换为网络字节顺序,反之亦然?如果是这样,那么您可以在可变长度结构中对数据进行字节交换.如果将其转换为使用向量,则编写用于序列化/反序列化数据包的方法是有意义的.这些方法会将其转移到连续缓冲区或从连续缓冲区转移,并考虑字节顺序.
同样,您可能需要考虑对齐和包装.
你永远不能继承Packet
.如果你这样做,那么子类的成员变量将与数组重叠.
而不是malloc
和free
,你可以使用Packet* p = ::operator new(size)
和::operator delete(p)
,因为它struct Packet
是一个POD类型,并且目前不会受益于其默认构造函数及其析构函数被调用.这样做的(潜在)好处是全局operator new
使用全局新处理程序和/或异常处理错误,如果这对您很重要.
可以使变长度结构惯用法与new和delete运算符一起使用,但不是很好.您可以operator new
通过实现创建一个采用数组长度的自定义static void* operator new(size_t size, unsigned int bitlength)
,但您仍然需要设置bitlength成员变量.如果使用构造函数执行此操作,则可以使用稍微冗余的表达式Packet* p = new(len) Packet(len)
来分配数据包.相比于使用全局我看到的唯一的好处operator new
和operator delete
将是你的代码的客户端可以只调用delete p
代替::operator delete(p)
.将分配/释放包装在单独的函数中(而不是delete p
直接调用)只要正确调用它们就可以了.
如果您从未添加构造函数/析构函数,则使用malloc/free进行分配的赋值运算符或虚函数是安全的.
它在c ++圈子中不受欢迎,但我认为如果你在代码中记录它就可以使用它.
对您的代码的一些评论:
struct Packet { unsigned int bitlength; unsigned int data[]; };
如果我记得正确声明一个没有长度的数组是非标准的.它适用于大多数编译器,但可能会给你一个警告.如果要符合要求,请声明长度为1的数组.
Packet* CreatePacket(unsigned int length) { Packet *output = (Packet*) malloc((length+1)*sizeof(unsigned int)); output->bitlength = length; return output; }
这可行,但您不考虑结构的大小.将新成员添加到结构后,代码将中断.最好这样做:
Packet* CreatePacket(unsigned int length) { size_t s = sizeof (Packed) - sizeof (Packed.data); Packet *output = (Packet*) malloc(s + length * sizeof(unsigned int)); output->bitlength = length; return output; }
并在数据包结构定义中写入注释,数据必须是最后一个成员.
顺便说一句 - 用一次分配来分配结构和数据是一件好事.您可以通过这种方式将分配数量减半,并且还可以改善数据的局部性.如果分配大量软件包,这可以提高性能.
不幸的是,c ++并没有提供一个很好的机制来做到这一点,所以你经常在现实世界的应用程序中得到这样的malloc/free hacks.
这没关系(并且是C的标准做法).
但这对C++来说不是一个好主意.
这是因为编译器会自动为您生成一整套其他方法.这些方法不明白你有欺骗行为.
例如:
void copyRHSToLeft(Packet& lhs,Packet& rhs) { lhs = rhs; // The compiler generated code for assignement kicks in here. // Are your objects going to cope correctly?? } Packet* a = CreatePacket(3); Packet* b = CreatePacket(5); copyRHSToLeft(*a,*b);
使用std :: vector <>它更安全,工作正常.
我也打赌它会在优化器启动后与您的实现一样高效.
或者,boost包含一个固定大小的数组:http:
//www.boost.org/doc/libs/1_38_0/doc/html/array.html