在矢量上使用调整大小时,矢量内部结构中的unique_ptr不会编译

unique_ptr in structure inside vector doesn't compile when resize used on vector

本文关键字:unique 编译 结构 ptr 调整 小时 内部      更新时间:2023-10-16

VS2010

我有一个内部有unique_ptr的结构。 然后我对这种结构有一个vector。 如果我尝试调整矢量的大小(或使用保留),则会出现编译错误。 下面是一个精简的示例,它仍然表现出问题。

struct Test
{
    unique_ptr<int> pValue;
};
void test()
{
    // this doesn't compile
    vector<Test> testVector;
    testVector.resize(5);
    // this also doesn't compile
    testVector.reserve(5);
    // this, of course, compiles
    vector<unique_ptr<int>> testVector2;
    testVector2.resize(5);
    testVector2.reserve(5);
}

我得到的错误是关于访问unique_ptr私有成员(分配运算符)的抱怨。 编译器正在尝试动态构造Test &Test::operator =(const Test &)Test::Test(const Test &)。 我不明白为什么调整大小操作需要调用这些函数中的任何一个(如果需要,为什么它不直接调用默认构造函数? 它们都存在问题,因为由于const,不可能用unique_ptr制作任何一个。

我不想打断你和自己的谈话。

但答案是VS2010尚未完全实现C++11规范(这需要一些时间旅行)。 Test应该有一个默认的 noexcept 移动构造函数,该构造函数调用unique_ptr移动构造函数。 VS2010 不实现此隐式Test移动构造函数。 如果是这样,您的完整示例将按预期编译和运行。 vector将使用 noexcept 移动构造函数在需要时移动内容。

(另一种情况,写出并发布问题导致答案)

答案当然是unique_ptr<>没有复制语义。 即便如此,我还是能够使用上述安排,直到我需要打电话给resize()。 我没有想到的是,resize()可能必须将块和其中的项目移动到另一个内存块。 这就是复制发生的时候。 尽管它只是非常临时的,但它仍然违反了复制过程中unique_ptr<>的唯一性。

更让我困惑的是,由于unique_ptr<>没有复制语义,vector<unique_ptr<>>也不应该工作。 但答案必须是已经为这种情况编写了模板专用化。

我可能也可以为vector<Test>编写一个模板专用化,以避免默认情况下向量类的延迟复制,从而避免上述编译器错误。 但是我对这个结构的使用不需要性能,所以让它使用shared_ptr<>及其复制语义可以完成我需要的一切。