Deleting Window Copy Operations
Why do we delete the copy constructor and assignment operator in the Window
class? What would happen if we didn't?
When we manage resources like SDL windows, we need to be careful about how our objects are copied. Let's explore why deleting these operations is important:
The Problem
Without deleting the copy operations, the compiler would generate default versions that perform shallow copies. This would lead to multiple Window
objects trying to manage the same SDL_Window*
:
#include <SDL.h>
class Window {
public:
Window() {
SDLWindow = SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
0
);
}
~Window() {
SDL_DestroyWindow(SDLWindow);
}
// Copy operations NOT deleted
SDL_Window* SDLWindow;
};
int main() {
SDL_Init(SDL_INIT_VIDEO);
{
Window WindowA;
// Creates a shallow copy
Window WindowB{WindowA};
// Both WindowA and WindowB now point to the
// same SDL_Window. When this scope ends,
// both destructors will try to destroy
// the same window!
}
SDL_Quit();
return 0;
}
Runtime Error: Attempted to destroy window that was already destroyed
The Solution
By deleting the copy operations, we prevent these issues:
#include <SDL.h>
class Window {
public:
Window() {
SDLWindow = SDL_CreateWindow(
"My Program",
100, 200, 600, 300,
0
);
}
~Window() {
SDL_DestroyWindow(SDLWindow);
}
// Prevent copying
Window(const Window&) = delete;
Window& operator=(const Window&) = delete;
SDL_Window* SDLWindow;
};
Moving Instead of Copying
If you need to transfer window ownership between objects, you can implement move operations instead:
#include <SDL.h>
class Window {
public:
Window() {
SDLWindow = SDL_CreateWindow(
"My Program",
100, 200, 600, 300, 0
);
}
~Window() {
SDL_DestroyWindow(SDLWindow);
}
// Prevent copying
Window(const Window&) = delete;
Window& operator=(const Window&) = delete;
// Allow moving
Window(Window&& Other) noexcept {
SDLWindow = Other.SDLWindow;
Other.SDLWindow = nullptr;
}
Window& operator=(Window&& Other) noexcept {
if (SDLWindow) {
SDL_DestroyWindow(SDLWindow);
}
SDLWindow = Other.SDLWindow;
Other.SDLWindow = nullptr;
return *this;
}
SDL_Window* SDLWindow;
};
This pattern of deleting copy operations while allowing moves is common when working with unique resources like windows, file handles, and network connections.
Window Configuration
Explore window creation, configuration, and event handling using SDL's windowing system