C++从堆创建结构体数组时出现编译错误与警告求助
编译错误与警告问题解答
问题代码
#include <iostream> struct { uint8_t m_data; int size; } BufferCustom; class MyClass { private: int x, y; const int CONST_BUFFER_SIZE = 10; struct BufferCustom *m_BufferPtr; public: MyClass(int xx, int yy) : x(xx), y(yy) { m_BufferPtr = new struct BufferCustom[CONST_BUFFER_SIZE]; } virtual ~MyClass() { if (m_BufferPtr){ delete [] m_BufferPtr; m_BufferPtr = nullptr; } } // user defined copy constructor MyClass(const MyClass& rhs) : x{ rhs.x }, y{ rhs.y } { std::cout << "User defined copy constructor invoked."; } MyClass& operator=(const MyClass &rhs) { std::cout << "Assignment operator called\n"; return *this; } }; int main() { MyClass o1{ 1, 2 }; MyClass o2 = o1; o2 = o1; }
遇到的错误与警告
- 编译错误:构造函数中
m_BufferPtr = new struct BufferCustom[CONST_BUFFER_SIZE];提示Allocation of incomplete type struct BufferCustom - 编译警告:析构函数中
delete [] m_BufferPtr;提示Deleting pointer to incomplete type 'struct BufferCustom' may cause undefined behavior
原因分析
你写的struct { ... } BufferCustom;是定义了一个匿名结构体类型,并同时创建了一个名为BufferCustom的该类型变量,而非定义名为BufferCustom的结构体类型。
当你在MyClass中声明struct BufferCustom *m_BufferPtr;时,编译器会认为你要声明一个指向名为BufferCustom的结构体的指针,但这个结构体类型从未被正式定义过——之前的代码只是创建了匿名结构体的变量,没有定义名为BufferCustom的结构体类型,因此编译器会将struct BufferCustom视为不完整类型(incomplete type)。
而new[]和delete[]操作都需要知道类型的完整定义(比如内存大小、析构函数信息等),对不完整类型执行这些操作必然触发错误和警告。
修复方案
先正式定义struct BufferCustom类型,再根据需求创建变量。修改后的代码如下:
#include <iostream> // 先定义命名的结构体类型 struct BufferCustom { uint8_t m_data; int size; }; class MyClass { private: int x, y; const int CONST_BUFFER_SIZE = 10; BufferCustom *m_BufferPtr; // 直接使用已定义的类型名,无需重复写struct public: MyClass(int xx, int yy) : x(xx), y(yy) { m_BufferPtr = new BufferCustom[CONST_BUFFER_SIZE]; } virtual ~MyClass() { if (m_BufferPtr){ delete [] m_BufferPtr; m_BufferPtr = nullptr; } } // user defined copy constructor MyClass(const MyClass& rhs) : x{ rhs.x }, y{ rhs.y } { std::cout << "User defined copy constructor invoked.\n"; // 补充深拷贝逻辑,避免多个对象共享同一块堆内存 m_BufferPtr = new BufferCustom[CONST_BUFFER_SIZE]; for(int i=0; i<CONST_BUFFER_SIZE; i++){ m_BufferPtr[i] = rhs.m_BufferPtr[i]; } } MyClass& operator=(const MyClass &rhs) { std::cout << "Assignment operator called\n"; if(this != &rhs){ x = rhs.x; y = rhs.y; // 补充深拷贝逻辑,防止内存泄漏和重复释放 delete[] m_BufferPtr; m_BufferPtr = new BufferCustom[CONST_BUFFER_SIZE]; for(int i=0; i<CONST_BUFFER_SIZE; i++){ m_BufferPtr[i] = rhs.m_BufferPtr[i]; } } return *this; } }; int main() { MyClass o1{ 1, 2 }; MyClass o2 = o1; o2 = o1; }
额外说明:原代码的拷贝构造函数和赋值运算符未处理动态分配的m_BufferPtr,会导致浅拷贝问题——多个对象共享同一块堆内存,析构时重复释放引发未定义行为,修复代码中补充了深拷贝逻辑。
内容的提问来源于stack exchange,提问作者Maverick447
相关产品推荐
相关产品推荐

