c++ - 通过 protected 构造函数和静态成员函数强制使用 std::shared_ptr 以创建实例和 std::make_shared

标签 c++ std shared-ptr make-shared

这个问题在这里已经有了答案:





How do I call ::std::make_shared on a class with only protected or private constructors?

(17 个回答)


1年前关闭。




我有一些只能通过 std::shared_ptr 使用的类.这些类的实例并非设计为通过在堆栈上分配它们或通过new 的原始指针直接使用。 .我目前通过使构造函数 protected 来执行此操作并拥有 static实际执行对象实例化并返回 shared_ptr 的成员函数到对象:

class Example {
protected:
    Example() { }
public:
    static std:shared_ptr<Example> create() { return std::shared_ptr<Example>(new Example()); }
};
我知道这不是防弹的,因为您仍然可以调用 get()shared_ptr ,但作为支持使用的指示似乎是合理的。
但是,我不能使用 std::make_shared()因为构造函数是protected ,而且我知道 make_shared() 具有内存分配/性能优势.
以上是不好的做法,还是有办法使用make_shared()不制作构造函数public ?

最佳答案

有一个老技巧是给另一个函数有限的权限来制作一个对象;你传递一个 token 。

struct Example_shared_only {
private:
  // permission token.  explicit constructor ensures
  // you have to name the type before you can create one,
  // and only Example_shared_only members and friends can
  // name it:
  struct permission_token_t {
    explicit permission_token_t(int) {}
  };
public:
  // public ctor that requires special permission:
  Example_shared_only( permission_token_t ) {}
  // delete special member functions:
  Example_shared_only()=delete;
  Example_shared_only(Example_shared_only const&)=delete;
  Example_shared_only(Example_shared_only &&)=delete;
  Example_shared_only& operator=(Example_shared_only const&)=delete;
  Example_shared_only& operator=(Example_shared_only &&)=delete;
  // factory function:
  static std::shared_ptr<Example_shared_only>
  make_shared() {
    return std::make_shared<Example_shared_only>( permission_token_t(0) );
  }
};
现在Example_shared_only::make_shared()返回 shared_ptr使用 make_shared 创建的, 没有其他人可以用它做很多事情。
如果您可以使用更现代的 C++ 方言,我们可以做得更好:
template<class F>
struct magic_factory {
  F f;
  operator std::invoke_result_t<F const&>() const { return f(); }
};

struct Example2 {
  static std::shared_ptr<Example2> make() {
    return std::make_shared<Example2>( magic_factory{ []{ return Example2{}; } } );
  }
private:
  Example2() = default;
};
Live example .
这需要 为了保证省略。magic_factory可以转换为您的工厂函数生成的任何内容,并保证省略就地构建该对象。它在其他上下文中具有更好的用途,但在这里它允许您导出构造函数以进行共享。
传递给 magic_factory 的 lambda是 Example2 的隐含 friend ,这使它可以访问私有(private) ctor。保证省略意味着具有签名 ()->T 的函数可以调用创建T “就地”,没有任何逻辑拷贝。make_shared<T>试图构建它的T使用论点。 C++检查operator T当这种情况发生时;我们的magic_factory有一个这样的operator T .所以它被使用。
它做了类似的事情
::new( (void*)ptr_to_storage ) Example2( magic_factory{ lambda_code } )
(如果您不熟悉,这称为“新放置”——它声明“请在 Example2 指向的位置构建 ptr_to_storage 对象)。
保证省略的美基本传递到lambda_code Example2的地址正在创建(又名 ptr_to_storage ),并且对象就在那里构造。

关于c++ - 通过 protected 构造函数和静态成员函数强制使用 std::shared_ptr 以创建实例和 std::make_shared,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64543557/

相关文章:

c++ - 关于 std::reduce vs2017 中的未知数?

c++ - 如何在没有编译器的情况下在 Linux 上安装 gcc

c++ - 对 makefile 无法识别的文件所做的更改

c++ - nullptr_t驻留在哪里?

c++ - 删除 boost::shared_ptr 的内容

c++ - 你什么时候会使用 std::auto_ptr 而不是 boost::shared_ptr?

C++ 智能指针性能以及与简单包装指针的差异

C++ 指针 - 语法和失败的程序

c++ - 序列点、条件和优化

c++ - 固定大小的容器,旧元素将被删除