c++ - 将使用 PIMPL 习语的类存储在 std::vector 中
问题描述
我正在编写一个应用程序,该应用程序需要将使用 PIMPL 习惯用法的类的对象存储在std::vector
. 因为该类用于std::unique_ptr
存储指向其实现的指针并且std::unique_ptr
不可复制,所以该类本身不可复制。std::vector
在这种情况下应该仍然可以工作,因为该类仍然是可移动的。
为了避免创建副本,我尝试使用emplace_back
将元素直接构造到 中vector
,但由于某种原因,它仍然抱怨它正在尝试调用复制构造函数!
我写了一个简单的例子来演示这个问题。
测试.h:
#pragma once
#include <memory>
// Simple test class implemented using the PIMPL (pointer to implementation) idiom
class Test
{
public:
Test(const int value);
~Test();
void DoSomething();
private:
// Forward declare implementation struct
struct Impl;
// Pointer to the implementation
std::unique_ptr<Impl> m_impl;
};
测试.cpp
#include "test.h"
#include <iostream>
// Implementation struct definition
struct Test::Impl
{
Impl(const int value)
: m_value(value)
{}
void DoSomething()
{
std::cout << "value = " << m_value << std::endl;
}
private:
int m_value;
};
// Construct the class and create an instance of the implementation struct
Test::Test(const int value)
: m_impl(std::make_unique<Impl>(value))
{}
Test::~Test() = default;
// Forward function calls to the implementation struct
void Test::DoSomething()
{
m_impl->DoSomething();
}
主.cpp:
#include "test.h"
#include <vector>
int main()
{
std::vector<Test> v;
// Even though I'm using "emplace_back" it still seems to be invoking the copy constructor!
v.emplace_back(42);
return 0;
}
当我尝试编译此代码时,出现以下错误:
error C2280: 'Test::Test(const Test &)': attempting to reference a deleted function
这就引出了两个问题……
为什么即使我明确使用了它仍试图使用复制构造函数
emplace_back
?我怎样才能让它编译没有错误?该对象是可移动的,因此根据标准它应该能够存储在
std::vector
.
解决方案
将它们添加Test(Test&&) noexcept;
到您的 cpp 文件中。Test& operator=(Test&&) noexcept;
=default
您可能应该在使用Test(const int value)
时明确表示。
至少在现代 gcc/clang=default
中,您可以在标题中移动 ctor。您不能这样做,operator=
因为它可以删除左侧指针,也不能删除零参数构造函数(与构造默认删除器有关?)或析构函数(必须调用默认删除器)。
推荐阅读
- javascript - Alt 标记被空格分隔。如何传递文本?
- java - 当我引用复合键时,无法找到具有逻辑名称错误的列
- php - 405 不允许 Github PHP
- android - 选择文本并显示自定义菜单而不是默认上下文菜单
- c++ - 在 Golang 中将 C 指针转换为 2D 切片
- javascript - 快速车把,无法将选中的属性绑定到复选框
- reactjs - 将 SVGR 与 Webpack 一起使用并配置为输出 TypeScript 时出现语法错误
- rest - Camunda 将消息与正在运行的流程实例相关联,启动新的流程实例
- powershell - PowerShell SSL/TLS 错误与 Invoke-RestMethod 命令
- node.js - process.uncaughtException 不能在 express 中工作