我是C ++的新手(来自Java / PHP)。基本上,我需要创建一个容器类,它将包含一个指向虚拟类实例(Base类)的唯一/共享指针的引用。我无法编译这段代码(我正在使用MSVC 2015)。
编译错误是:
error C2280: 'std::unique_ptr<Base,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
以下是重现此问题的示例应用程序:
#include <iostream>
#include <memory>
class Base {
public:
virtual void foo() const = 0;
virtual void bar() const = 0;
};
class Derived : public Base {
public:
void foo() const override {
std::cout << "foo" << std::endl;
};
void bar() const override{
std::cout << "bar" << std::endl;
};
};
class ContainerUnique {
public:
ContainerUnique() {
ptr = nullptr;
}
void assignPtr(const Base &instance) {
auto ptr = std::make_unique<Base>(instance);
ptr.swap(ptr);
};
std::unique_ptr<Base> getPtr() {
return ptr;
};
private:
std::unique_ptr<Base> ptr;
};
class ContainerShared {
public:
ContainerShared() {
ptr = nullptr;
}
void assignPtr(const Base &instance) {
auto ptr = std::make_shared<Base>(instance);
ptr.swap(ptr);
};
std::shared_ptr<Base> getPtr() {
return ptr;
};
private:
std::shared_ptr<Base> ptr;
};
int main() {
Derived derived1 = Derived();
Derived derived2 = Derived();
ContainerUnique cu = ContainerUnique();
ContainerShared cs = ContainerShared();
cu.assignPtr(derived1);
cs.assignPtr(derived2);
std::unique_ptr<Base> uptr = cu.getPtr();
std::shared_ptr<Base> sptr = cs.getPtr();
return 0;
}
请咨询
答案 0 :(得分:0)
您应该考虑对象所有权以及对象所在的位置(堆栈或堆),这些都不是您在Java中必须关注的。
因为ContainerUnique
有一个unique_ptr
成员,我推断它的目的是拥有指向的对象。它有义务删除它。这与其余部分不一致,因为derived1
在堆栈上,所以不需要被任何东西拥有,也不能删除。相反,假设我们在堆上创建了derived1
:
auto derived1 = std::make_unique<Derived>();
在堆上创建它,以便它需要管理,并通过将其指针存储在unique_ptr
中来识别我们拥有该对象。要使用unique_ptr
转让所有权,我们必须调整界面:
// Interface
void ContainerUnique::assignPtr(std::unique_ptr<Base> instance);
// Call site
cu.assignPtr(std::move(derived1));
如果我们采用原始引用或指针,则接口或调用站点中没有任何内容可以反映所有权的预期更改。如果我们采用引用到Base,并调用std::make_unique
我们正在制作副本,并制作Base的副本(丢失任何派生数据)。采用unique_ptr
可能是沟通所有权转移的最明确方式。
把它放在一起:
#include <memory>
struct Base {
virtual void foo() const = 0;
virtual void bar() const = 0;
};
struct Derived : Base {
void foo() const override { }
void bar() const override { }
};
class ContainerUnique {
public:
void assignPtr(std::unique_ptr<Base> instance) {
ptr.swap(instance);
};
std::unique_ptr<Base> getPtr() {
return std::move(ptr);
};
private:
std::unique_ptr<Base> ptr;
};
int main() {
auto derived1 = std::make_unique<Derived>();
auto cu = ContainerUnique();
cu.assignPtr(std::move(derived1));
auto uptr = cu.getPtr();
}