将使用PIMPL习惯用法的类存储在std::vector中



我正在编写一个应用程序,该应用程序需要在std::vector中存储使用PIMPL习惯用法的类的对象。因为类使用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;
};

test.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();
}

main.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

这引出了两个问题。。。

  1. 为什么尽管我明确使用了emplace_back,它仍试图使用复制构造函数?

  2. 我如何才能在没有错误的情况下编译它?对象是可移动的,因此根据标准,它应该能够存储在std::vector中。

在cpp文件中添加Test(Test&&) noexcept;Test& operator=(Test&&) noexcept;,然后添加=default

你可能应该让Test(const int value)显式,当你在它。

至少在现代的gcc/clang中,您可以=default移动标头中的ctor。不能对operator=执行此操作,因为它既可以删除左侧指针,也可以删除零参数构造函数(与构造默认删除程序有关?(或析构函数(必须调用默认删除程序(。

最新更新