Maxbad`Blog

限定对象只能在堆上创建

2021-03-08 · 2 min read

限定对象在堆上创建的需求

C++对象的一些使用场景其实已经有这种隐喻了,比如一个对象从std::enable_shared_from_this派生,当我们调用this->shared_from_this()的前提条件是这个对象已经被创建为shared_ptr,如果是一个栈对象去调用shared_from_this时会crash,所以使用派生于std::enable_shared_from_this的对象时,限定它只能在堆上创建可以保证代码的安全性。

struct dummy{
    class token{
    private:
        token(){}
        friend dummy;
    };

    static std::shared_ptr<dummy> create(){
      return std::make_shared<dummy>(token{});
    }

    dummy(token) : dummy() {
    }

private:
    dummy(){}
};

int main() {
  dummy d{}; //compile error
  dummy d(token{}); //compile error
  auto ptr = dummy::create(); //ok
}

这个代码借助了一个私有内部类token来避免在栈上创建dummy对象,因为外面无法访问这个token,只有它的友元类dummy才能访问token。另外一个问题是dummy的构造函数还是私有的,为什么这次改造之后可以用std::make_shared了?因为这里先通过public的dummy(token)去构造dummy对象的,然后dummy通过代理构造函数dummy()去真正构造一个dummy对象。

这个token在这里有两个作用,一个是用来避免在栈上构造dummy对象,一个是提供一个public的构造函数给std::make_shared使用。对于创建一个std::unique_ptr对象来说思路也是一样的,读者可以自行实现。至此,我们比较完美地实现了限定对象只能在堆上创建的目标。