C ++ 11:从当前实例创建unique_ptr的解决方法(this)

时间:2014-12-09 01:38:00

标签: c++ c++11 this unique-ptr

我有一个函数SomeFunc,其unique_ptr类型A作为参数。我想从类中调用SomeFunc并将当前实例作为参数发送给函数。我使用以下,我得到一个分段错误。除了在这里使用原始指针之外,为什么会这样,并且有解决方法吗?

#include <iostream>
#include <memory>

using namespace std;

class A;

extern void SomeFunc(const unique_ptr<A>& Some1);

class A {
 public:
  A() {}
  void Success() { cout << "Hey\n"; }
  void Func() {
    const unique_ptr<A> Some1(this);
    SomeFunc(Some1);
  }
};

void SomeFunc(const unique_ptr<A>& Some1) { Some1->Success(); }

int main() {
  A a;
  a.Func();
  return 0;
}

2 个答案:

答案 0 :(得分:2)

当unique_ptr超出范围时,它会尝试调用delete this。但是this没有动态分配,因此是seg错误。

你可以在SomeFunc之后立即调用Some1.release(),然后在unique_ptr超出范围之前,这是一个有点难看的黑客。

如果更改界面是可以接受的,更好的解决方案可能只是更改您的界面以接受const A&,并将其称为SomeFunc(*this)

答案 1 :(得分:0)

你可以这样做 - 它只适用于API期望unique_ptr到完全抽象类的情况。基本上,您可以创建一个转发到您的实例的派生类...即给定

struct Abstract {
    virtual void someFun() = 0;
};

T apiFun(unique_ptr<Abstract> ptr);

和你的班级

struct MyImpl : public Abstract {
   virtual void someFun() { cout << "Hello world!" << std::endl; }
};

然后你可以

struct AbstractProxy : public Abstract {
    Abstract* other;
    AbstractProxy(Abstract* other): other(other) {}
    virtual void someFun() { other->someFun(); }
};

- 当然这实际上不会删除你的课程。但是因为你实际上无法阻止你的类在堆栈上创建(在这种情况下,删除它会导致bad things(TM)发生),你可能不想这样做。如果要确保始终删除已创建的实例,则可能不应公开构造函数,而是提供一个自由函数,该函数始终在堆上创建类的实例。或者你的unique_ptr期望能够删除你的班级。

在这种情况下,似乎API被破坏了。 unique_ptr只能由相应实例的所有者持有,而且该功能似乎并不试图声明您的实例的所有权。