错误 C2280 / 在 std::vector 中实例化对象时复制构造函数出现问题?

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

本文关键字:构造函数 复制 问题 对象 实例化 C2280 std vector 错误      更新时间:2023-10-16

我目前正在按照ChiliTomatoNoodle的教程编写我的第一个应用程序,并根据我的需要修改他的代码。在这样做并实现一个简单的 WindowManager 类时,该类的目的是将所有窗口实例存储在 std::vector 和类似的东西中,我收到以下错误消息:

C:\Program Files (x86(\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.23.28105\include\xmemory(758,1(:

错误 C2280:"窗口::窗口(常量窗口 &(":尝试引用已删除的函数(编译源文件 src\cpp\窗口管理器.cpp(

问题似乎出在addWindow函数中,其中窗口被实例化并存储在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++));
}

我已经将push_back更改为emplace_back以避免复制(?(,但它并没有解决问题。

然后还有一个getter(似乎很好,没有复制任何东西(:

Window& WindowManager::getWindow(const unsigned short id) {
for (Window &element : this->Wnd) {
if (element.Id == id) {
return element;
}
}
}

这是Window类标头:

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;
};

编辑:

感谢所有答案和评论,指出参数必须直接传递给emplace_back方法。事实证明,向量仍然复制了对象(不知道为什么..(,但我可以通过改用std::list来解决这个问题,它没有这种行为。

Window复制构造函数是用delete声明的,但是当你将现有的Window对象传递到emplace_back()中时,emplace_back()的实现将尝试使用其参数就地构造另一个Window对象。它执行此操作的唯一方法是尝试使用已删除的复制构造函数。

你可以声明一个复制构造函数,使用push_back(),或者更好地调用emplace_back()使用另一个Window构造函数的参数,这将避免复制。

此行创建一个临时窗口,该窗口将被移动(如果有移动构造函数(或复制(如果有复制构造函数(到vector- 但您的Window缺少两者:

this->Wnd.emplace_back(Window(name, x, y, width, height, windowClass, style,
this->IdGenNum++));

使用emplace_back,您无需创建临时参数,因为您提供给emplace_back的参数完美地转发给Window的构造函数,因此不会进行不必要的移动或复制:

this->Wnd.emplace_back(name, x, y, width, height, windowClass, style, this->IdGenNum++);

尽管这应该足以解决这个直接问题,但您的Window类看起来应该支持移动,但不一定支持复制。