【发布时间】:2021-09-12 15:10:33
【问题描述】:
我正在编写一个应用程序,它需要在std::vector 中存储使用 PIMPL 习惯用法的类的对象。因为该类使用std::unique_ptr 来存储指向其实现的指针并且std::unique_ptr 不可复制,所以该类本身不可复制。 std::vector 在这种情况下应该仍然有效,因为该类仍然是可移动的。
为了避免创建副本,我尝试使用emplace_back 将元素直接构造到vector,但由于某种原因它仍然抱怨它正在尝试调用复制构造函数!
我写了一个简单的例子来演示这个问题。
test.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
这就引出了两个问题……
-
为什么即使我明确使用了
emplace_back,它仍试图使用复制构造函数? -
我怎样才能让它编译没有错误?该对象是可移动的,因此根据标准它应该能够存储在
std::vector中。
【问题讨论】:
-
the class is still movable- 是吗?Test b(std::move(a));有效吗? -
您应该能够在
emplace_back中调用移动构造函数。似乎此链接可能是您正在寻找的内容:stackoverflow.com/questions/35404932/… -
考虑使用
std::shared_ptr使您的课程可复制。 -
您声明了析构函数,因此编译器甚至不会尝试提供移动构造函数。它确实提供了一个复制构造函数,但已被弃用。您可以
Test(Test&&) = default;重新启用移动构造函数。然后,您可能会遇到在main.cpp中使用不完整类型的问题:)
标签: c++ c++11 vector move-semantics pimpl-idiom