C++ 如何避免使用反向引用的共享指针引用的聚合类型的两阶段构造?

C++ 如何避免使用反向引用的共享指针引用的聚合类型的两阶段构造?,c++,constructor,smart-pointers,C++,Constructor,Smart Pointers,假设我有一个类型聚合器和一个聚合对象。前者通过shared\ptrs知道后者的集合。后者具有指向前者的唯一回指针: struct Aggregatee { private: Aggregator& aggregator; Aggregatee(Aggregator& aggregator) : aggregator{aggregator} { // PROBLEM HERE: // I want to put `this

假设我有一个类型
聚合器
和一个
聚合对象
。前者通过
shared\ptr
s知道后者的集合。后者具有指向前者的唯一回指针:

struct Aggregatee {
  private:
    Aggregator& aggregator;
    Aggregatee(Aggregator& aggregator)
      : aggregator{aggregator} {
      // PROBLEM HERE:
      //   I want to put `this` into the aggregation list,
      //   but I have no clue how to properly refer to `this`
      //   because I don't have the smart pointer object, yet.
    }
    Aggregatee(Aggregatee const& from) { /* ... */ }
  public:
    template <typename Args...>
    static std::shared_ptr<Aggregatee> create(Args... args) {
      return std::make_shared<Aggregatee>(args...);
    }
};

struct Aggregator {
  std::set<std::shared_ptr<Aggregatee>> aggregation;
};
struct聚合对象{
私人:
聚合器&聚合器;
聚合对象(聚合器和聚合器)
:聚合器{aggregator}{
//这里的问题是:
//我想把“this”放在汇总列表中,
//但我不知道该如何恰当地提到这个`
//因为我还没有智能指针对象。
}
聚合对象(聚合对象常量和起始值){/*…*/}
公众:
模板
静态标准::共享ptr创建(Args…Args){
返回std::使_共享(args…);
}
};
结构聚合器{
std::集合聚合;
};
显然,我可以在使用私有
寄存器
函数
make_shared
之后推迟在
聚合器
对象中注册
聚合对象
,但由于对象的初始化暂时不一致,它闻起来像是两个阶段


是否有任何已知的解决方案?

根据您的应用程序,您可以将静态创建方法从聚合对象移动到常规成员方法聚合器。然后您可以创建共享的_ptr并用相同的方法存储它


这假设聚合对象总是与聚合器关联。

您试图避免的实际上是一种非常常见的模式:创建聚合器(容器),然后创建聚合对象(元素)并将其插入容器中。可以使用传递给构造函数的后向指针创建元素,然后将其插入容器或后向指针

例如,考虑一个带有反向指针的二叉树,元素在叶子上创建,带有指向父节点的指针,指针立即存储在父节点中


至于您的特定问题,这是无法做到的,因为您无法在创建对象之前获得对象的
共享\u ptr
,即使使用
启用\u共享\u,您也无法使用侵入式共享指针。由于引用计数随后存在于共享对象中,聚合对象可以在其自己的构造函数中创建指向自身的共享指针

Boost有一个入侵指针类型的例子,或者您可以很容易地使用自己的指针类型

//共享基类型包含引用计数器;如何实现
//引用计数取决于您的实现。
结构聚合对象:公共共享{
私人:
聚合器&聚合器;
聚合对象(聚合器和聚合器):聚合器{Aggregator}{
//Boost允许将原始指针隐式转换为侵入式
//指针,但您的入侵指针类型可能不会。
aggregator.aggregation.insert(intrusive_ptr(this));
}
聚合对象(聚合对象常量和起始值){/*…*/}
公众:
模板
静态侵入式\u ptr创建(Args…Args){
返回新的侵入性_ptr(args…);
}
};
结构聚合器{
std::集合聚合;
};
您必须注意的一点是,聚合对象在构造之后确实存储在智能指针中

Aggregatee aggregatee(aggregator);  // Very bad!
intrusive_ptr<Aggregatee> aggregatee(new Aggregatee(aggregator));  // Good
聚合器聚合器(聚合器);//非常糟糕!
侵入式聚合对象(新聚合对象(聚合器));//好
另外,你最好确保你的聚合器在聚合对象完全构建之前一直保持着入侵的ptr,否则聚合对象将在构造函数退出之前被销毁


因此,这种方法有一些需要注意的地方,但据我所知,这是最接近你所要求的。

是的,但构建一个
聚合对象
(请注意,我是在聚合,不是在编写!)要直观得多。此外,这是一种简化,因为实际上有两种不同类型的
Aggregator1
Aggregator2
具有原始帖子的属性。因此,
Aggregatee
始终只与一个
Aggregator
关联,但不是唯一的—它还与不同类型的对象关联。如果这是一篇作文,你的方法就会奏效。
Aggregatee aggregatee(aggregator);  // Very bad!
intrusive_ptr<Aggregatee> aggregatee(new Aggregatee(aggregator));  // Good