C++代码遇Segmentation Fault:初始化列表可行,拷贝构造函数失效
你的段错误核心原因是Button类的浅拷贝问题:默认拷贝构造函数只会逐成员复制,如果Button内部持有裸指针(比如指向动态内存、SDL纹理/窗口句柄这类系统资源),临时Button对象销毁时会释放这些资源,而你赋值给Game的成员变量后,成员变量里的指针就指向了已释放的内存,后续访问必然触发段错误。
以下是几种可行的解决方案:
1. 给Button实现深拷贝的拷贝构造函数和赋值运算符
手动编写拷贝逻辑,复制资源而非仅复制指针,确保每个Button实例拥有独立的资源副本。同时实现赋值运算符(遵循拷贝交换惯用法),避免内存泄漏和重复释放。
示例代码:
#include <SDL2/SDL.h> #include <algorithm> // 用于std::swap class Button { private: SDL_Texture* m_texture; SDL_Rect m_rect; std::string m_text; SDL_Renderer* m_renderer; // 假设需要持有渲染器指针 public: // 普通构造函数 Button(SDL_Renderer* renderer, const std::string& text, int x, int y) : m_renderer(renderer), m_text(text), m_rect{x, y, 100, 50} { // 创建纹理的逻辑 SDL_Surface* surface = TTF_RenderText_Solid(/* 字体指针 */, text.c_str(), {255,255,255,255}); m_texture = SDL_CreateTextureFromSurface(renderer, surface); SDL_FreeSurface(surface); } // 拷贝构造函数:深拷贝资源 Button(const Button& other) : m_renderer(other.m_renderer), m_text(other.m_text), m_rect(other.m_rect) { // 从原纹理复制出新的纹理 SDL_Surface* surface = SDL_GetSurfaceFromTexture(other.m_texture); m_texture = SDL_CreateTextureFromSurface(m_renderer, surface); SDL_FreeSurface(surface); } // 赋值运算符:拷贝交换惯用法 Button& operator=(Button other) { std::swap(m_texture, other.m_texture); std::swap(m_rect, other.m_rect); std::swap(m_text, other.m_text); return *this; } // 析构函数:释放资源 ~Button() { if (m_texture) { SDL_DestroyTexture(m_texture); } } };
2. 使用智能指针管理Button内部资源
将Button中的裸指针替换为std::unique_ptr或std::shared_ptr,配合自定义删除器处理系统资源的释放。默认的拷贝构造/赋值会自动处理资源的转移或共享,无需手动编写深拷贝逻辑。
示例代码:
#include <SDL2/SDL.h> #include <memory> // 自定义SDL纹理删除器:确保资源正确释放 struct SDLTextureDeleter { void operator()(SDL_Texture* tex) const { if (tex) { SDL_DestroyTexture(tex); } } }; class Button { private: // 使用unique_ptr管理纹理,独占资源所有权 std::unique_ptr<SDL_Texture, SDLTextureDeleter> m_texture; SDL_Rect m_rect; std::string m_text; public: Button(SDL_Renderer* renderer, const std::string& text, int x, int y) : m_text(text), m_rect{x, y, 100, 50} { SDL_Surface* surface = TTF_RenderText_Solid(/* 字体指针 */, text.c_str(), {255,255,255,255}); m_texture.reset(SDL_CreateTextureFromSurface(renderer, surface)); SDL_FreeSurface(surface); } // 如果需要拷贝Button实例,改用shared_ptr共享资源 // std::shared_ptr<SDL_Texture, SDLTextureDeleter> m_texture; };
- 用
unique_ptr时,赋值需要通过std::move转移资源所有权,避免浅拷贝; - 用
shared_ptr时可直接拷贝,资源会通过引用计数管理,最后一个持有者销毁时才释放资源。
3. 直接原位构造Game的Button成员
如果不想修改Button类,可以给Button添加带参数的构造函数,直接在Game的构造函数初始化列表中创建Button成员,跳过默认构造后赋值的步骤,从根本上避免临时对象的创建。
示例代码:
class Game { private: Button m_startButton; Button m_exitButton; public: // 直接在初始化列表中构造Button,无需临时对象 Game(SDL_Renderer* renderer) : m_startButton(renderer, "Start", 100, 200), m_exitButton(renderer, "Exit", 300, 200) {} };
内容的提问来源于stack exchange,提问作者DR4NKR1D3R
相关产品推荐
相关产品推荐

