错误 C2280/在 std::vector 中实例化 Object 时复制构造函数有问题?
Error C2280 / Problem with Copy Constructor while instantiating an Object in std::vector?
我目前正在按照 ChiliTomatoNoodle 的教程编写我的第一个应用程序,并根据我的需要修改他的代码。在这样做并实现一个简单的 WindowManager class 时,它的目的是将所有 window 实例存储在 std::vector 和类似的东西中,我收到以下错误消息:
C:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.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)
问题似乎出在 addWindow
函数中,其中 window 被实例化并存储在 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 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;
};
编辑:
感谢所有指出参数必须直接传递给 emplace_back
方法的回答和评论。事实证明,向量仍然复制了 object(不知道为什么..),但我可以通过使用 std::list
来解决这个问题,它没有这种行为。
Window
复制构造函数是用 delete
声明的,但是当您将现有的 Window
对象传递给 emplace_back()
时,emplace_back()
的实现将尝试使用它的参数就地构造另一个 Window
对象。它可以做到这一点的唯一方法是尝试使用已删除的复制构造函数。
您可以声明一个复制构造函数,使用 push_back()
,或者使用其他 Window
构造函数的参数更好地调用 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
class 看起来应该支持移动但不一定支持复制。
我目前正在按照 ChiliTomatoNoodle 的教程编写我的第一个应用程序,并根据我的需要修改他的代码。在这样做并实现一个简单的 WindowManager class 时,它的目的是将所有 window 实例存储在 std::vector 和类似的东西中,我收到以下错误消息:
C:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.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)
问题似乎出在 addWindow
函数中,其中 window 被实例化并存储在 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 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;
};
编辑:
感谢所有指出参数必须直接传递给 emplace_back
方法的回答和评论。事实证明,向量仍然复制了 object(不知道为什么..),但我可以通过使用 std::list
来解决这个问题,它没有这种行为。
Window
复制构造函数是用 delete
声明的,但是当您将现有的 Window
对象传递给 emplace_back()
时,emplace_back()
的实现将尝试使用它的参数就地构造另一个 Window
对象。它可以做到这一点的唯一方法是尝试使用已删除的复制构造函数。
您可以声明一个复制构造函数,使用 push_back()
,或者使用其他 Window
构造函数的参数更好地调用 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
class 看起来应该支持移动但不一定支持复制。