可变长结构体放入std::vector等容器会产生错误,如下:
#include <iostream>
#include <vector>
using namespace std;
struct node
{
int size; //list的大小
int list[0];
};
int main()
{
std::vector<node> mySet;
int a[2] = {1,2};
int b[3] = {77,4,5};
int c[1] = {8};
node * a1 = (node *)malloc(sizeof(node) + 8);
node * a2 = (node *)malloc(sizeof(node) + 12);
node * a3 = (node *)malloc(sizeof(node) + 4);
memcpy(a1->list, a, 8); a1->size = 2;
memcpy(a2->list, b, 12); a2->size = 3;
memcpy(a3->list, c, 4); a3->size = 1;
mySet.push_back(*a1);
mySet.push_back(*a2);
mySet.push_back(*a3);
std::cout<<"按地址偏移输出:\n";
int * p = (int *)&mySet[0];
for(int j = 0; j < 10; j++) {
std::cout << *(p++) << "\t";
}
std::cout<<"\n按下标索引输出:\n";
for(int i = 0; i < 3; i++) {
std::cout << "size:" << mySet[i].size << "\tlist:\t";
for(int j = 0; j < mySet[i].size; j++) {
std::cout << mySet[i].list[j] << "\t";
}
std::cout<<"\n";
}
std::cout<<"end\n";
return 0;
};
输出结果为:
按地址偏移输出:
2 3 1 1610612736 2 3 0 1610612736 0 1610612736
按下标索引输出:
size:2 list: 3 1
size:3 list: 1 1610612736 2
size:1 list: 1610612736
end
可以看到std::vector是不能够存入可变长结构体的,只有第一个数存储正确了,且std::vector默认所有的结构体长度为4字节,
但如果改变结构体为:
struct node
{
int size; //list的大小
int list[1]; //这里变成1
};
输出的结果就会变为:
按地址偏移输出:
2 1 3 77 1 8 0 0 0 805306368
按下标索引输出:
size:2 list: 1 3
size:3 list: 77 1 8
size:1 list: 8
end
这里std::vector默认所有的结构体长度为8字节,每个结构体有两个数存储正确。
由此可以猜想,std::vector决定其内元素分配空间大小依靠的是sizeof(), 如果元素是可变长结构,且不能够通过sizeof()体现大小变化,则是不能存入std::vector容器的。