Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可以将pimpl类放入向量中吗_C++_Class_C++11_Smart Pointers - Fatal编程技术网

C++ 可以将pimpl类放入向量中吗

C++ 可以将pimpl类放入向量中吗,c++,class,c++11,smart-pointers,C++,Class,C++11,Smart Pointers,我使用PImpl Ideom实现了一个类: class FooImpl {}; class Foo { unique_ptr<FooImpl> myImpl; public: Foo(); ~Foo(); }; 现在我想把它放到一个std::向量中 void Bar() { vector<Foo> testVec; testVec.resize(10); } 但是当我这样做的时候,我得到了一个编译错误VC++2013 错误C2280:'

我使用PImpl Ideom实现了一个类:

class FooImpl {};

class Foo
{
   unique_ptr<FooImpl> myImpl;
public:
   Foo();
   ~Foo();
};
现在我想把它放到一个std::向量中

void Bar()
{
   vector<Foo> testVec;
   testVec.resize(10);
}
但是当我这样做的时候,我得到了一个编译错误VC++2013

错误C2280:'std::unique\u ptr>::unique\u ptrconst std::unique\u ptr&':尝试引用已删除的函数

我在testVec.emplace_返回时得到了相同的错误;和testVec.push_backsd::moveFoo

作为一种变通方法,使用vector似乎可行,但我不明白上面的代码为什么不起作用

工作示例:

由于std::unique\u ptr不可复制,因此类Foo没有有效的复制构造函数

你可以:


示例:

因此,向量模板试图访问Foo类的复制构造函数。您尚未提供副本构造函数,因此编译器尝试生成一个默认实现,该实现在所有成员上调用副本构造函数。由于std::unique_ptr没有来自另一个std::unique_ptr的复制构造函数,这是合乎逻辑的,因为它不知道如何复制对象,编译器无法为Foo生成赋值运算符,因此失败。因此,您可以为Foo类提供一个复制构造函数,并决定如何处理指针:

#include <memory>
#include <vector>

using namespace std;
class FooImpl {};

class Foo
{
    unique_ptr<FooImpl> myImpl;
public:
    Foo()
    {
    }
    ~Foo()
    {
    }
    Foo(const Foo& foo)
    {
        // What to do with the pointer?
    }
    Foo& operator= (const Foo& foo)
    {
        if (this != &foo)
        {
            // What to do with the pointer?
        }
        return *this;
    }
};

int main(int argc, char** argv)
{
    vector<Foo> testVec;
    testVec.resize(10);
    return 0;
}

但是为什么resize或emplace_back必须首先复制?@nikie,将赋值和复制构造函数设为私有,您将得到一个模板实例化错误,显示调用它们的完整路径。resize需要擦除,erase需要_-Move,_-Move'使用赋值运算符。@m.s.顺便说一句,提供的示例仍然没有在VC中编译,所以严格地说。resize调用需要的是赋值操作,而不是移动构造函数,可能是VC/gcc/clang中的差异。由于op显然使用VC,这不是一个解决方案。实现复制构造函数重用赋值运算符似乎不是一个好主意,因为复制构造函数是在未初始化的对象上调用的,因此如果使用未初始化的对象作为左侧参数调用赋值运算符,则会得到未定义的行为。赋值运算符希望初始化的对象作为左侧参数。@SergeRogatch好的,这似乎有问题,在我使用C++11之前,您能再详细说明一下吗?我理解逻辑,但就我只分配成员变量而言,这不是很好吗?我的意思是副本执行器不也调用所有成员执行器吗?你能给我一个未定义行为的例子吗?我很想了解结果。你是对的,复制构造函数将在输入前调用成员变量的默认构造函数{如果它们不是由复制构造函数初始化列表中的用户初始化的:。但我认为原始指针(例如void*)和基元数据类型的变量(例如int)将包含垃圾。这在复制构造函数中是允许的,因为它是在未初始化的对象上调用的。但是赋值运算符希望初始化的对象是左s赋值运算符可能会删除原始指针void*,这会损坏内存uninitialized@SergeRogatch好的,我明白你的意思了,我认为还有更可怕的事情。至于原始指针成员——这取决于用户是否要做一个适当的初始值设定项列表,并将它们设为null,然后检查赋值运算符中的值,tha至少我会这么做。谢谢你对你的陈述的解释:但我仍然坚持我的信念,如果代码写得正确,就可以了。另一件事是重复操作,可能在初始值设定项列表和赋值运算符中重叠,但这是另一回事。
#include <memory>
#include <vector>

using namespace std;
class FooImpl {};

class Foo
{
    unique_ptr<FooImpl> myImpl;
public:
    Foo()
    {
    }
    ~Foo()
    {
    }
    Foo(const Foo& foo)
    {
        // What to do with the pointer?
    }
    Foo& operator= (const Foo& foo)
    {
        if (this != &foo)
        {
            // What to do with the pointer?
        }
        return *this;
    }
};

int main(int argc, char** argv)
{
    vector<Foo> testVec;
    testVec.resize(10);
    return 0;
}