You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 08:43:27