数组 class 中的 malloc 和 memcpy 问题
Problem with malloc and memcpy in array class
我已经开始为 List
class 编写一些代码,但我迷路了。我的 Arduino 项目需要它——我不能使用 STL。
这是代码。
#include <iostream>
template <typename T>
class List
{
public:
List<typename T>()
{
m_Count = 0;
m_Data = nullptr;
}
~List()
{
free(m_Data);
}
void Push(const T& element)
{
m_Count++;
T* alloc = (T*)malloc(size_t(sizeof(T) * m_Count));
memcpy(alloc, m_Data, m_Count * sizeof(T));
*(m_Data + sizeof(T) * (m_Count - 1)) = element;
}
T* operator [](unsigned int x) const
{
return (m_Data + x * sizeof(T));
}
private:
T* m_Data;
uint64_t m_Count;
};
struct Vertex
{
int x;
int y;
};
int main()
{
List<Vertex> list;
list.Push({ 0, 1 });
list.Push({ 2, 3 });
list.Push({ 4, 5 });
std::cout << list[0]->x << list[1]->x << list[2]->x;
}
问题出在Push
方法的某处:当我调用memcpy
时,程序触发了编译断点。
根本问题在*(m_Data + sizeof(T) * (m_Count - 1)) = element;
行。在这里,您试图将给定的 element
复制到 old(即预先存在的)m_Data
数组中;这将是 nullptr
第一次调用 Push
函数(并且每隔一次调用一个元素太小)†.
因此,您需要先释放旧数据(free(m_Data)
),然后将新分配的内存分配给该指针(m_Data = alloc
),然后才复制element
到该数组的最后一个元素。
但是,正如其他人所说,为什么要在 C++ 中使用 malloc
和 free
?下面的代码将这些调用替换为 new[]
和 delete[]
(尽管如果可能的话,使用 std::vector
可能会是 easier/better/safer)。
#include <iostream>
template <typename T>
class List {
public:
List<T>() { // Don't need "typename" here!
m_Count = 0;
m_Data = nullptr;
}
~List() {
delete[] m_Data;
}
void Push(const T& element) {
m_Count++;
T* alloc = new T[m_Count];
for (uint64_t i = 0; i < m_Count - 1; ++i) alloc[i] = m_Data[i]; // Copy old data (if any)
delete[] m_Data; // Release old data
m_Data = alloc; // Assign newly-allocated memory to m_Data
m_Data[m_Count - 1] = element; // Why use pointer arithmetic when you have the [] operator?
}
T* operator [](unsigned int x) const {
return &m_Data[x];
}
private:
T* m_Data;
uint64_t m_Count;
};
struct Vertex {
int x;
int y;
};
int main()
{
List<Vertex> list;
list.Push({ 0, 1 });
list.Push({ 2, 3 });
list.Push({ 4, 5 });
std::cout << list[0]->x << list[1]->x << list[2]->x << std::endl;
std::cout << list[0]->y << list[1]->y << list[2]->y << std::endl;
return 0;
}
我对你的代码做了一些其他的 'minor improvements' (你的 operator []
看起来很可疑,因为在进行指针运算时,指向对象的大小在本质上被考虑在内) ;还有其他 可以 制作,但是恕我直言,这与您发布的代码相差太远。
† 实际上,它在您的代码中 总是 是 nullptr
,因为您永远不会向它分配任何其他内容。
我已经开始为 List
class 编写一些代码,但我迷路了。我的 Arduino 项目需要它——我不能使用 STL。
这是代码。
#include <iostream>
template <typename T>
class List
{
public:
List<typename T>()
{
m_Count = 0;
m_Data = nullptr;
}
~List()
{
free(m_Data);
}
void Push(const T& element)
{
m_Count++;
T* alloc = (T*)malloc(size_t(sizeof(T) * m_Count));
memcpy(alloc, m_Data, m_Count * sizeof(T));
*(m_Data + sizeof(T) * (m_Count - 1)) = element;
}
T* operator [](unsigned int x) const
{
return (m_Data + x * sizeof(T));
}
private:
T* m_Data;
uint64_t m_Count;
};
struct Vertex
{
int x;
int y;
};
int main()
{
List<Vertex> list;
list.Push({ 0, 1 });
list.Push({ 2, 3 });
list.Push({ 4, 5 });
std::cout << list[0]->x << list[1]->x << list[2]->x;
}
问题出在Push
方法的某处:当我调用memcpy
时,程序触发了编译断点。
根本问题在*(m_Data + sizeof(T) * (m_Count - 1)) = element;
行。在这里,您试图将给定的 element
复制到 old(即预先存在的)m_Data
数组中;这将是 nullptr
第一次调用 Push
函数(并且每隔一次调用一个元素太小)†.
因此,您需要先释放旧数据(free(m_Data)
),然后将新分配的内存分配给该指针(m_Data = alloc
),然后才复制element
到该数组的最后一个元素。
但是,正如其他人所说,为什么要在 C++ 中使用 malloc
和 free
?下面的代码将这些调用替换为 new[]
和 delete[]
(尽管如果可能的话,使用 std::vector
可能会是 easier/better/safer)。
#include <iostream>
template <typename T>
class List {
public:
List<T>() { // Don't need "typename" here!
m_Count = 0;
m_Data = nullptr;
}
~List() {
delete[] m_Data;
}
void Push(const T& element) {
m_Count++;
T* alloc = new T[m_Count];
for (uint64_t i = 0; i < m_Count - 1; ++i) alloc[i] = m_Data[i]; // Copy old data (if any)
delete[] m_Data; // Release old data
m_Data = alloc; // Assign newly-allocated memory to m_Data
m_Data[m_Count - 1] = element; // Why use pointer arithmetic when you have the [] operator?
}
T* operator [](unsigned int x) const {
return &m_Data[x];
}
private:
T* m_Data;
uint64_t m_Count;
};
struct Vertex {
int x;
int y;
};
int main()
{
List<Vertex> list;
list.Push({ 0, 1 });
list.Push({ 2, 3 });
list.Push({ 4, 5 });
std::cout << list[0]->x << list[1]->x << list[2]->x << std::endl;
std::cout << list[0]->y << list[1]->y << list[2]->y << std::endl;
return 0;
}
我对你的代码做了一些其他的 'minor improvements' (你的 operator []
看起来很可疑,因为在进行指针运算时,指向对象的大小在本质上被考虑在内) ;还有其他 可以 制作,但是恕我直言,这与您发布的代码相差太远。
† 实际上,它在您的代码中 总是 是 nullptr
,因为您永远不会向它分配任何其他内容。