C++自定义类赋值报no suitable copy constructor及C2679错误求助
错误原因定位
两个核心语法问题直接触发编译报错:
- 自定义拷贝构造函数的参数为
CTextureBuffer&非const左值引用,无法绑定到CTextureBuffer(image->w, image->h, image->pixels)生成的临时右值对象。 - 赋值运算符采用值传递方式接收参数,传参时需要调用拷贝构造函数构造形参,拷贝构造匹配失败后编译器判定没有符合要求的
=运算符,抛出C2679错误。
修复方案
基础版本(浅拷贝,匹配现有业务逻辑)
你当前的业务逻辑只需要拷贝纹理参数和指针,不需要复制纹理数据,直接使用编译器默认生成的拷贝逻辑即可,修复后代码如下:
class CTextureBuffer { public: int m_width = 0; int m_height = 0; void* m_data = nullptr; CTextureBuffer(int width = 0, int height = 0, void* data = nullptr) : m_width(width), m_height(height), m_data(data) {} // 拷贝构造加const修饰,支持绑定临时右值和const对象 CTextureBuffer(const CTextureBuffer& other) = default; // 赋值运算符返回类引用,符合C++运算符重载规范 CTextureBuffer& operator=(const CTextureBuffer& other) = default; // 可选:添加移动语义实现,提升临时对象赋值的性能 CTextureBuffer(CTextureBuffer&& other) = default; CTextureBuffer& operator=(CTextureBuffer&& other) = default; };
进阶版本(深拷贝,独立管理纹理资源)
如果需要让CTextureBuffer持有纹理数据的所有权,不依赖SDL_Surface的生命周期,可以实现深拷贝逻辑:
class CTextureBuffer { public: int m_width = 0; int m_height = 0; void* m_data = nullptr; // 存储每个像素的字节数,根据SDL_Surface的format计算 int m_pitch = 0; CTextureBuffer(int width = 0, int height = 0, void* data = nullptr, int pitch = 4) : m_width(width), m_height(height), m_pitch(pitch) { if (data && width > 0 && height > 0) { // 分配内存拷贝纹理数据 m_data = malloc(width * height * pitch); memcpy(m_data, data, width * height * pitch); } } CTextureBuffer(const CTextureBuffer& other) { m_width = other.m_width; m_height = other.m_height; m_pitch = other.m_pitch; if (other.m_data) { m_data = malloc(m_width * m_height * m_pitch); memcpy(m_data, other.m_data, m_width * m_height * m_pitch); } } CTextureBuffer& operator=(const CTextureBuffer& other) { if (this == &other) return *this; // 释放原有内存 if (m_data) free(m_data); m_width = other.m_width; m_height = other.m_height; m_pitch = other.m_pitch; if (other.m_data) { m_data = malloc(m_width * m_height * m_pitch); memcpy(m_data, other.m_data, m_width * m_height * m_pitch); } else { m_data = nullptr; } return *this; } ~CTextureBuffer() { if (m_data) free(m_data); } // 可选移动语义 CTextureBuffer(CTextureBuffer&& other) noexcept { m_width = other.m_width; m_height = other.m_height; m_pitch = other.m_pitch; m_data = other.m_data; other.m_data = nullptr; other.m_width = other.m_height = other.m_pitch = 0; } CTextureBuffer& operator=(CTextureBuffer&& other) noexcept { if (this == &other) return *this; if (m_data) free(m_data); m_width = other.m_width; m_height = other.m_height; m_pitch = other.m_pitch; m_data = other.m_data; other.m_data = nullptr; other.m_width = other.m_height = other.m_pitch = 0; return *this; } };
业务代码优化
- 添加入参前置校验,避免第一个文件名为空的非法输入
- 补充SDL_Surface资源释放逻辑,避免内存泄漏:如果用浅拷贝版本,需要自行管理所有加载的SDL_Surface生命周期;如果用深拷贝版本,拷贝完纹理数据后即可调用
SDL_FreeSurface释放image对象。
优化后的业务代码示例:
bool CTexture::Load(CArray<CString>& fileNames, bool flipVertically) { m_fileNames = fileNames; // 前置校验第一个文件名不能为空 if (fileNames.IsEmpty() || fileNames[0]->IsEmpty()) { fprintf(stderr, "First cubemap face filename can not be empty\n"); return false; } CTextureBuffer texBuf; for (auto const& fileName : fileNames) { if (fileName->Length()) { SDL_Surface* image = IMG_Load((char*)(*fileName)); if (!image) { fprintf(stderr, "Couldn't find '%s'\n", (char*)(*fileName)); return false; } // 深拷贝版本调用:传入pitch参数,注意根据实际SDL_Surface格式调整 texBuf = CTextureBuffer(image->w, image->h, image->pixels, image->pitch / image->w); // 深拷贝版本可直接释放surface SDL_FreeSurface(image); } m_buffers.Append(texBuf); } return true; }
内容的提问来源于stack exchange,提问作者Razzupaltuff
相关产品推荐
相关产品推荐

