编辑:添加了构造函数并添加了功能
请考虑以下三个步骤:
//ONE
template<typename T>
class List1 {
private:
uint32_t capacity;
uint32_t used;
T* data;
void checkGrow() {
if (used < capacity)
return;
T* old = data;
capacity*=2;
data = (T*)new char[sizeof(T) * capacity];
memcpy(data, old, sizeof(T)*used);
delete (void*)old;
}
public:
List1() : capacity(1), used(0), data((T*)new char [sizeof(T)]) {}
List1(uint32_t initialSize) :
capacity(initialSize), used(0), data((T*)new char[sizeof(T)]) {}
List1(const List1& orig) :
capacity(orig.capacity), used(orig.used), data((T*)new char[used * sizeof(T)]) {
memcpy(data, orig.data, used * sizeof(T));
}
uint32_t serializeSize() const { return sizeof(used) + used*sizeof(T); }
char* read(char* p) {
used = *(uint32_t*)p;
p += sizeof(uint32_t);
data = (T*)new char[used*sizeof(T)];
memcpy(p, data, used * sizeof(T));
return p + used*sizeof(T);
}
char* write(char* p) {
*(uint32_t*)p = used;
p += sizeof(uint32_t);
memcpy(p, data, used * sizeof(T));
return p + used * sizeof(T);
}
~List1() { delete [] data; }
void add(const T& v) {
checkGrow();
data[used++] = v;
}
uint32_t getUsed() const{
return used;
}
uint32_t getCapacity() const{
return capacity;
}
//const T& operator [](int i) const { return data[i]; }
//T& operator [](int i) { return data[i]; }
T getData (int i) const{
return data[i];
}
uint32_t size() const { return used * sizeof(T); }
};
//TWO
List1<uint32_t> temp=in.readList<uint32_t>(); // <List1<uint32_t>>();
//BREAKPOINT HERE
for(uint i=0;i<15;i++){
//cout<<temp[i]<<endl;
cout<<temp.getData(i)<<endl;
}
//THREE
template<typename T>
T _read() {
T temp = *(T*)p;
p += sizeof(T);
availRead -= sizeof(T);
return temp;
}
template<typename T>
T read(){
//cout << (uint64_t)p << endl;
checkAvailableRead(sizeof(T));
return _read<T>();
}
template<typename T>
List1<T> readList(){
uint32_t len = read<uint32_t>();
List1<T> temp(len);
for (uint i = 0 ; i < len; i++){
T val =read<T>();
temp.add(val);
//HERE: For some reason code does not work without this print statement
//cout<<temp.getData(i)<<endl;
}
return temp;
}
基本上,问题在于从getData返回后,数据值会发生变化,如下所示。
gdb) p/u *temp.data@15
$1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
(gdb) p/u *temp.data@15
$2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
(gdb) p/u *data@15
$3 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
[New Thread 8444.0xad8]
(gdb) p/u *data@15
$4 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
[New Thread 8444.0x214c]
(gdb) p/u *temp.data@15
$5 = {0, 1, 2, 3, 4, 5, 83, 0, 2150008464, 1, 3742232646, 0, 168272, 6, 0}
由于某种原因,将打印语句添加到readList可以解决此问题,但这不是一个合理的解决方案。我在代码上尝试了几种不同的变体,但没有一个起作用。
我不确定问题是什么,甚至不确定如何开始调试,因为问题发生在return语句和循环的下一个迭代之间(没有任何内容可进入其中)。
任何建议将不胜感激。
答案 0 :(得分:1)
List1(const List1& orig) :
capacity(orig.capacity), used(orig.used), data((T*)new char[used * sizeof(T)]) {
memcpy(data, orig.data, used * sizeof(T));
}
要使List1
正常工作,绝对不能有List1
大于实际分配大小的capacity
。但是,如果List1
的{{1}}大于orig
,则会创建一个违反此不变式的新capacity
。
您可能是说used
。
同一问题在这里:
capacity(orig.used)
如果将List1(uint32_t initialSize) :
capacity(initialSize), used(0), data((T*)new char[sizeof(T)]) {}
设置为capacity
,则不能仅分配1个initialSize
的空间。
这也损坏了T
。用delete (void*)old;
分配的内容,必须用new[]
释放。
请注意,delete[]
仅可用于保存没有构造函数或析构函数的POD类型(普通旧数据)。如果您尝试使用List1
来处理更复杂的内容,那么您的设计将步入歧途。