如何将拥有 CDialogEx 的 std::unique_ptr 添加到 std::vector 以避免“尝试引用已删除的函数”?

问题描述 投票:0回答:1

C++ 和 Windows 正在互相争斗,我需要让他们停止。

我有一个 Visual Studio 2022 生成的类,它实现了

CDialogEx
,我需要将其添加到能够插入的数组中。这很难。

Visual Studio 2022 为对话框生成的类如下所示:

class SignPage : public CDialogEx
{
    DECLARE_DYNAMIC(SignPage)

public:
    SignPage(CWnd* pParent = nullptr);   // standard constructor
    virtual ~SignPage();

// Dialog Data
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_SIGN_PAGE };
#endif

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

    DECLARE_MESSAGE_MAP()
};

Visual Studio 生成的类的实现如下所示:

// SignPage.cpp : implementation file
//

#include "pch.h"
#include "App.h"
#include "afxdialogex.h"
#include "SignPage.h"


// SignPage dialog

IMPLEMENT_DYNAMIC(SignPage, CDialogEx)

SignPage::SignPage(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_SIGN_PAGE, pParent)
{

}

SignPage::~SignPage()
{
}

void SignPage::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(SignPage, CDialogEx)
END_MESSAGE_MAP()


// SignPage message handlers

我知道能够插入的数组是

std::vector
,但是将任何Windows生成的对象插入
std::vector
会导致“尝试引用已删除的函数”错误,因为Windows已删除其对象中的复制和移动函数。

我不希望能够插入的数组以任何方式干扰 Windows 提供的对象,因此我理解

std:unique_ptr
是我所需要的,以便我将指向 Windows 提供的对象的指针添加到列表中。

我像这样实例化对象和向量,编译器喜欢它:

std::vector<std::unique_ptr<SignPage>> m_dlgs;
std::unique_ptr<SignPage> upm_dlg1 = std::make_unique<SignPage>();

现在我尝试将

upm_dlg1
插入到 m_dlgs 中,如下所示:

std::vector<std::unique_ptr<SignPage>>::iterator it;
it = m_dlgs.begin();
m_dlgs.insert(it, upm_dlg1); <---- error happens here

添加上面最后一行会导致模板内出现编译错误,呈现唯一指针,如下所示:

1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include\xmemory(700,82): error C2280: 'std::unique_ptr<SignPage,std::default_delete<SignPage>>::unique_ptr(const std::unique_ptr<SignPage,std::default_delete<SignPage>> &)': attempting to reference a deleted function

有谁知道我必须采取什么步骤来解决这个问题?

我的局限性是:

  • 我需要添加到能够插入的数组中的对象是由 Visual Studio 生成的,以便 Windows 受益。我修改这些对象的选择是有限的。

  • 编译器错误是在我理解的实现

    unique_ptr
    的模板深处触发的。我假设这就是 C++ 编译器错误的乐趣。

  • 我被引导相信

    std::vector
    是我应该使用的集合,但事实可能并非如此,有人可以证实吗?我不需要排序或任何其他复杂性,只是一个简单的数组,我可以在其中插入和删除,而无需以任何方式接触列表中的对象。

c++ windows collections mfc
1个回答
1
投票

这一行:

m_dlgs.insert(it, upm_dlg1);

尝试在 upm_dlg1 内创建

std::vector
副本

但由于它是
std::unique_ptr
,因此无法复制:
std::unique_ptr
的复制构造函数是deleted,这就是错误“尝试引用已删除的函数”的原因。

相反,您应该按以下方式使用 std::vector

 将对象移动
std::move
中:

//----------------vvvvvvvvv------------
m_dlgs.insert(it, std::move(upm_dlg1));

旁注:

std::move
并没有真正移动任何东西:

std::move 用于指示对象 t 可以“移出”, 即允许资源从 t 有效转移到另一个 对象。

实际上,这是通过转换为 R 值引用来完成的。
然而,最终结果正是您所需要的,因为它将使用

std::vector::insert
的适当重载来触发,执行移动而不是复制。

© www.soinside.com 2019 - 2024. All rights reserved.