I am currently programming my first application by following ChiliTomatoNoodle's tutorials and modify his code to my needs. While doing so and implementing a simple WindowManager class, which has the purpose to store all the window instances in a std::vector and similar things, I got following error message:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.23.28105\include\xmemory(758,1):
error C2280: 'Window::Window(const Window &)': attempting to reference a deleted function (compiling source file src\cpp\WindowManager.cpp)
The Problem seems to lie in the addWindow
function, where the window is instantiated and stored in std::vector<Window> Wnd
:
void WindowManager::addWindow(unsigned short x, unsigned short y, unsigned short width, unsigned short height, const char* name, Window::WindowClass& windowClass, DWORD style) {
this->Wnd.emplace_back(Window(name, x, y, width, height, windowClass, style, this->IdGenNum++));
}
I already changed push_back
to emplace_back
to maybe avoid copying (?), but it didn't solve the problem.
Then there's also a getter (that seems to be fine and not copying anything):
Window& WindowManager::getWindow(const unsigned short id) {
for (Window &element : this->Wnd) {
if (element.Id == id) {
return element;
}
}
}
And here is the Window
class header:
class Window {
private: // Friends
friend class WindowManager;
public: // Nested Classes
class WindowClass {
...
};
private: // Variables and Instances
unsigned short Id; // Received by WindowManager on Creation
const char* Name;
HWND Handle;
...
public: // Constructors and Deconstructors
Window(const Window&) = delete;
Window(
const char* name,
unsigned short x,
unsigned short y,
unsigned short width,
unsigned short height,
WindowClass& windowClass,
DWORD style,
unsigned short id
);
~Window();
private: // Functions
...
public: // Operators
Window& operator=(const Window&) = delete;
};
Edit:
Thanks for all the answers and comments pointing out that the arguments have to be passed directly to the emplace_back
method. As it turned out, the vector still copied the object (no clue why..), but I could fix this by using std::list
instead, which doesn't have this behavior.
This line creates a temporary Window that will be moved (if there's a move constructor) or copied (if there's a copy constructor) to the vector
- but your Window
lacks both:
this->Wnd.emplace_back(Window(name, x, y, width, height, windowClass, style,
this->IdGenNum++));
With emplace_back
you don't need to create a temporary since the argument you give to emplace_back
are perfect forwarded to the constructor of Window
, so there will be no unnecessary move or copy being made:
this->Wnd.emplace_back(name, x, y, width, height, windowClass, style, this->IdGenNum++);
Although this should be enough to solve this immediate problem, your Window
class looks like it should support moving but not necessarily copying.