繁体   English   中英

使用指向 B 的成员 function 中的 class B 的指针初始化 class A 的std::shared_ptr 类型的成员

[英]Initializing a member with type std::shared_ptr<B> of a class A with a pointer to class B in a member function of B

我有以下代码:

class Cohomology;

struct EMField
{
     std::shared_ptr<Cohomology> coh;
     std::array<DIM> data;

     // other methods

}

class Cohomology
{
     private:
        // private members
     public:
        Cohomology(PList params)
        {
             // Constructor of the class
        }
        
        virtual ~Cohomology() {std::cout << "Cohomology destroyed" << std::endl;}

        void initializeField(EMField& field)
        {
             field.coh.reset(this);
             // other methods to initialize field.data using the private members
        }
}

但是 class Cohomology也有由SubCohomology实现的虚拟方法:

class SubCohomology : public Cohomology
{
     public:
        SubCohomology(PList params) {}
        
        ~Cohomology() {std::cout << "SubCohomology destroyed" << std::endl;}

        // Implementation of the virtual methods
}

因此,用于检查EMFields是否已初始化并可以操作的测试代码如下所示:

int main(int argc, char *argv[])
{
     // variables needed to initialize PList params
     PList params(); // construct params

     SubCohomology coh(params);

     EMField field;

     coh.initializeField(field);

}

代码编译,但运行它会产生这个错误:

SubCohomology destroyed
Cohomology destroyed
free(): invalid pointer
[machine:324808] *** Process received signal ***
[machine:324808] Signal: Aborted (6)
[machine:324808] Associated errno: Unknown error 32767 (32767)
[machine:324808] Signal code:  (24)
[machine:324808] [ 0] /usr/lib/libc.so.6(+0x38a40)[0x7f4ac0054a40]
[machine:324808] [ 1] /usr/lib/libc.so.6(+0x884dc)[0x7f4ac00a44dc]
[machine:324808] [ 2] /usr/lib/libc.so.6(gsignal+0x18)[0x7f4ac0054998]
[machine:324808] [ 3] /usr/lib/libc.so.6(abort+0xd7)[0x7f4ac003e53d]
[machine:324808] [ 4] /usr/lib/libc.so.6(+0x7c67e)[0x7f4ac009867e]
[machine:324808] [ 5] /usr/lib/libc.so.6(+0x9226c)[0x7f4ac00ae26c]
[machine:324808] [ 6] /usr/lib/libc.so.6(+0x940bc)[0x7f4ac00b00bc]
[machine:324808] [ 7] /usr/lib/libc.so.6(__libc_free+0x73)[0x7f4ac00b2a33]
[machine:324808] [ 8] /home/user/builddir/test_fields(_ZN13EMFieldILi0ELi1EED2Ev+0x83)[0x556db1fc0f73]
[machine:324808] [ 9] /home/user/builddir/test_fields(main+0x36e)[0x556db1fa205e]
[machine:324808] [10] /usr/lib/libc.so.6(+0x232d0)[0x7f4ac003f2d0]
[machine:324808] [11] /usr/lib/libc.so.6(__libc_start_main+0x8a)[0x7f4ac003f38a]
[machine:324808] [12] /home/user/builddir/test_fields(_start+0x25)[0x556db1fa3ba5]
[machine:324808] *** End of error message ***
Aborted (core dumped)

这发生在 function initializeField之后。 这是一个 memory 问题,可能与尝试free()不存在的资源有关。

我怀疑使用std::enable_shared_from_this可能有助于解决这个问题,但考虑到我的特殊问题,我不知道如何实现强制性 inheritance,因为我正在尝试初始化std::shared_ptr<Cohomology> coh class 成员上Cohomology class中的一个字段。

此处概述的示例对于理解如何使用它非常有帮助,但我不知道是否必须在EMField中嵌套另一个结构来实现它。 我也理解在这个问题中解决的问题:我们什么时候应该使用 std::enable_shared_from_this ,但我不能把它放在结构有std::shared_ptr作为成员的上下文中。

请理解可能会添加许多EMField对象,其std::shared_ptr<Cohomology>成员将所有字段指向相同的 object

谢谢你。

std::shared_ptr的存在是为了管理动态分配对象的生命周期。 对于具有自动存储持续时间(如coh )的 object,不需要(或不可能)此类管理。 它的使用寿命与其封闭的 scope 相关。 因此,指向coh的指针绝不能由std::shared_ptr管理。

相反,您应该考虑在接受std::shared_ptr<Cohomology>EMField中创建一个构造函数,并让调用者创建一个适当的动态分配的 object:

struct EMField
{
    std::shared_ptr<Cohomology> coh;
    // ...

    EMField(std::shared_ptr<Cohomology> c)
        : coh{c}
    {}

    // ...
};

int main(int argc, char *argv[])
{
    // variables needed to initialize PList params
    PList params(); // construct params

    auto coh = std::make_shared<SubCohomology>(params);

    EMField field(coh);

    // No longer needed since EMField's constructor initializes its
    // fields now
    // coh.initializeField(field);
}

演示


如果您绝对不想将您的上Cohomology EMField从调用者传递到 EMField 中,并且所有上Cohomology对象都应该动态分配,并且它们都应该由std::shared_ptr管理,那么,只有这样,是std::enable_shared_from_this工作的工具。

例子:

class Cohomology : public std::enable_shared_from_this<Cohomology>
{
    private:
        // private members
    protected:
        Cohomology(PList params)
        {
             // Constructor of the class
        }

        Cohomology(const Cohomology&) = delete;

    public:
        virtual ~Cohomology()
        {
            std::cout << "Cohomology destroyed\n";
        }

        static std::shared_ptr<Cohomology> create(PList params)
        {
            return std::shared_ptr<Cohomology>(new Cohomology(params));
        }

        void initializeField(EMField& field)
        {
             field.coh = shared_from_this();
             // ...
        }

        // ...
};

class SubCohomology : public Cohomology
{
    private:
        SubCohomology(PList params)
            : Cohomology(params)
        {}

    public:
        ~SubCohomology()
        {
            std::cout << "SubCohomology destroyed\n";
        }
        
        static std::shared_ptr<SubCohomology> create(PList params)
        {
            return std::shared_ptr<SubCohomology>(new SubCohomology(params));
        }

        // Implementation of the virtual methods
};

int main(int argc, char *argv[])
{
    // variables needed to initialize PList params
    PList params; // construct params

    std::shared_ptr<SubCohomology> coh = SubCohomology::create(params);

    EMField field;

    coh->initializeField(field);
}

演示

请注意,上同SubCohomologyCohomology现在具有非公共构造函数。 如果您从std::enable_shared_from_this继承,则不应允许任何对象不被std::shared_ptr管理,因此需要单独的工厂函数来确保这一事实。

  • initializeField 重置您的智能指针:删除 object
  • 我认为这种方法不适合 object,你可以在 Cohomology object 之外进行

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM