C++11 :从当前实例(此)进行unique_ptr的解决方法

C++11 : A workaround for making unique_ptr from current instance (this)

本文关键字:unique 进行 ptr 方法 解决 实例 C++11      更新时间:2023-10-16

我有一个函数SomeFunc它接受类型Aunique_ptr作为参数。我想从类内部调用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 << "Heyn"; }
  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;
}

当unique_ptr超出范围时,它会尝试调用delete this。 但是this不是动态分配的,因此出现了seg故障。

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

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

你可以这样做 - 只有当 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 应该只由相应实例的所有者持有,并且该函数似乎并没有试图声明实例的所有权。