Search code examples
c++windowswindowdesktop-applicationwindow-managers

Error C2280 / Problem with Copy Constructor while instantiating an Object in std::vector?


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.


Solution

  • 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.