【发布时间】:2019-10-09 19:23:08
【问题描述】:
我目前正在按照 ChiliTomatoNoodle 的教程编写我的第一个应用程序,并根据我的需要修改他的代码。在这样做并实现一个简单的 WindowManager 类时,该类的目的是将所有窗口实例存储在 std::vector 和类似的东西中,我收到以下错误消息:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.23.28105\include\xmemory(758,1):
错误 C2280: 'Window::Window(const Window &)': 试图引用已删除的函数(编译源文件 src\cpp\WindowManager.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;
};
编辑:
感谢所有答案和 cmets 指出参数必须直接传递给 emplace_back 方法。事实证明,向量仍然复制了对象(不知道为什么......),但我可以通过使用 std::list 来解决这个问题,它没有这种行为。
【问题讨论】:
-
为什么是
this->Wnd.emplace_back(Window(name, x, y, width, height, windowClass, style, this->IdGenNum++));而不是this->Wnd.emplace_back(name, x, y, width, height, windowClass, style, this->IdGenNum++);? -
因为我认为这是这样做的方法。 ^^' 我认为阅读而不是写作更清晰
Window似乎也解决不了任何问题?还是谢谢! -
emplace_back()使用您提供的参数构造向量元素类型。通过将Window(...)指定为参数,您首先构造了一个临时Window()对象,然后emplace_back()尝试使用Window的复制构造函数在向量内构造另一个Window,该构造函数一直是@987654341 @d。通过省略Window(...),仅在向量内部构造了1 个Window,使用name、x、y等变量直接作为该构造函数的参数。 -
@Splize "我认为阅读起来更清晰" 但是,
emplace_back并没有实现它的意图:在向量中创建对象,而不是复制它,正如push_back所做的那样。由于它会将其参数转发给Window的构造函数,并且如果它接收到Window const&类型的单个参数,则匹配该签名的唯一构造函数是复制构造函数。 “似乎也没有解决任何问题” 如果是这种情况,则问题不在emplace_back调用中。请提供minimal reproducible example。 -
push_back()不必复制。它可以移动。它在 C++11 和更高版本中被重载以接受右值,所以你可以这样做:this->Wnd.push_back(Window(...));当然,如果Window定义了一个移动构造函数会有所帮助。
标签: c++ windows window desktop-application window-managers