Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 共享\u from\u此从构造函数调用_C++_Boost - Fatal编程技术网

C++ 共享\u from\u此从构造函数调用

C++ 共享\u from\u此从构造函数调用,c++,boost,C++,Boost,我必须在容器中注册一个对象。 如果没有智能指针,我会使用如下内容: a_class::a_class() { register_somewhere(this); } boost::shared_ptr<a_class> create_a() { boost::shared_ptr<a_class> ptr(new a_class); ptr->init(); return ptr; } 对于智能指针,我应该使用这个中的shared

我必须在容器中注册一个对象。 如果没有智能指针,我会使用如下内容:

a_class::a_class()
{
    register_somewhere(this);
}
boost::shared_ptr<a_class> create_a()
{
    boost::shared_ptr<a_class> ptr(new a_class);
    ptr->init();
    return ptr;
}
对于智能指针,我应该使用这个中的
shared\u,但我不能在构造函数中使用它

有没有干净的方法来解决这个问题?在类似的情况下,你会怎么做? 我正在考虑引入一个
init
方法,以便在创建后立即调用,并将所有内容放入工厂函数中,如下所示:

a_class::a_class()
{
    register_somewhere(this);
}
boost::shared_ptr<a_class> create_a()
{
    boost::shared_ptr<a_class> ptr(new a_class);
    ptr->init();
    return ptr;
}
在我的程序中,
a_类
是一个实体,
b_类
是表示状态的具体类之一(在构造函数中,它只是开始状态)
a_类
需要指向当前状态的指针,
b_类
需要操作实体

a_类
负责创建和销毁b_类实例,从而维护对它们的共享ptr,但是
b_类
需要操作
a_类
,从而维护弱指针<代码>a_类
实例“生存”
b_类
实例


您是否建议在这种情况下避免使用智能指针?

如果您在构建过程中绝对需要共享的ptr,最好使用“init”函数。事实上,这是我能想到的唯一体面的方法。如果选择此路径,您可能应该有一个特殊的函数来创建这种类型的对象,以确保调用
init()

但是,根据注册对象的不同,最好使用指向构造函数中对象的普通指针,而不是共享的\u ptr,来指定要注册的对象。然后在析构函数中,您可以从管理器中注销对象。

为什么不使用

struct a_类:从\u中启用\u共享\u{
a_类(){
共享_ptr ptr(本);
在某处注册(ptr);
}
};
更新:以下是一个完整的工作示例:

#include <stdio.h>
#include <boost/smart_ptr/enable_shared_from_this.hpp>

struct a_class;
boost::shared_ptr<a_class> pa;

void register_somewhere(boost::shared_ptr<a_class> p)
{
    pa = p;
};

struct a_class : boost::enable_shared_from_this<a_class> {
private:
    a_class() {
        printf("%s\n", __PRETTY_FUNCTION__);
        boost::shared_ptr<a_class> ptr(this);
        register_somewhere(ptr);
    }

public:
    ~a_class() {
        printf("%s\n", __PRETTY_FUNCTION__);
    }

    static boost::shared_ptr<a_class> create()
    {
        return (new a_class)->shared_from_this();
    }
};

int main()
{
    boost::shared_ptr<a_class> p(a_class::create());
}
#包括
#包括
结构a_类;
boost::共享的ptr-pa;
某个地方的无效寄存器(boost::shared\u ptr p)
{
pa=p;
};
结构a_类:boost::从\u中启用\u共享\u{
私人:
a_类(){
printf(“%s\n”,函数);
boost::shared_ptr ptr(这个);
在某处注册(ptr);
}
公众:
~a_class(){
printf(“%s\n”,函数);
}
静态boost::共享的\u ptr create()
{
return(新的a_类)->shared_from_this();
}
};
int main()
{
boost::shared_ptr p(一个_类::create());
}
注意工厂函数a_class::create()。它的任务是确保只创建一个引用计数器。因为

boost::shared_ptr<a_class> p(new a_class);
boost::shared_ptr p(新的a_类);
导致创建两个引用计数器并双重删除对象

a_类
负责创建和销毁
b_类
实例

a_类
实例“幸存”
b_类
实例

考虑到这两个事实,
b_类
实例在
a_类
实例被销毁后尝试访问
a_类
实例应该没有危险,因为
a_类
实例负责销毁
b_类
实例

b_类
可以只保存一个指向其关联的
a_类
实例的指针。原始指针不表示任何适用于这种情况的所有权

在本例中,
a_类
是如何动态创建的,是聚合对象的一部分,等等。创建
a_类
的对象管理其生存期,就像
a_类
管理其实例化的
b_类
的生存期一样

例如


为此,我编写了自己的drop-in替换程序,用于
共享ptr
弱ptr
从该
启用共享。你可以在

与标准的enable_shared_相比,它允许在构造函数和析构函数中调用
shared_()
,而不需要辅助函数,且无空间开销


注意:只允许在DTOR中创建共享的ptr,只要它们只是临时创建的。也就是说,它们在dtor返回之前被销毁。

没有必要在您的代码中共享
(如您所示和解释)。
shared\u ptr
仅适用于共享所有权

你的
b_类
并不拥有它的
a_类
,事实上,它甚至比它更长寿,所以它应该只保留一个观察指针

如果
b_类
是多态的,并且
a_类
的操作涉及更改其
b_类
指针,则应使用
唯一的ptr

a类(u类);
b班
{
朋友班a_班;
a_类*mya;
b类(a类*p)
:mya(p){}
公众:
需要虚拟~b_class(){}//才能使unique_ptr工作
virtual void fiddle();//对mya做点什么
};
甲级
{
std::唯一的ptr myb;
公众:
a_类()
:myb(新b_类(this)){}
模板
无效更改_myb()
{
myb.重置(新B(本));
}
};

我为这个问题设计了一个助手类:

template <class Impl>
class ImmediatelySharedFromThis : public std::enable_shared_from_this<Impl> {
    typedef std::unique_ptr<void, std::function<void(void*)>> MallocGuard;
    typedef std::shared_ptr<Impl> SharedPtr;

    // disallow `new MyClass(...)`
    static void *operator new(size_t) = delete;
    static void *operator new[](size_t) = delete;
    static void operator delete[](void*) = delete;
protected:
    typedef std::pair<MallocGuard&, SharedPtr&> SharingCookie;

    ImmediatelySharedFromThis(SharingCookie cookie) {
        MallocGuard &ptr = cookie.first;
        SharedPtr &shared = cookie.second;
        // This single line contains the actual logic:
        shared.reset(reinterpret_cast<Impl*>(ptr.release()));
    }
public:
    // Create new instance and return a shared pointer to it.
    template <class ...Args>
    static SharedPtr create(Args &&...args) {
        // Make sure that the memory is free'd if ImmediatelySharedFromThis
        // is not the first base class, and the initialization
        // of another base class throws an exception.
        MallocGuard ptr(aligned_alloc(alignof(Impl), sizeof(Impl)), free);
        if (!ptr) {
            throw std::runtime_error("OOM");
        }

        SharedPtr result;
        ::new (ptr.get()) Impl(SharingCookie(ptr, result),
                               std::forward<Args>(args)...);
        return result;
    }

    static void operator delete(void *ptr) {
        free(ptr);
    }
};

class MyClass : public ImmediatelySharedFromThis<MyClass> {
    friend class ImmediatelySharedFromThis<MyClass>;

    MyClass(SharingCookie cookie, int some, int arguments) :
        ImmediatelySharedFromThis(cookie)
        // You can pass shared_from_this() to other base classes
    {
        // and you can use shared_from_this() in here, too.
    }
public:
    ....
};

...

std::shared_ptr<MyClass> obj = MyClass::create(47, 11); 
模板
类立即从此共享:public std::从该{
typedef std::unique_ptr MallocGuard;
typedef std::shared_ptr SharedPtr;
//不允许“新建MyClass(…)`
静态void*运算符new(size_t)=delete;
静态void*运算符new[](size\u t)=删除;
静态void运算符delete[](void*)=delete;
受保护的:
typedef std::pair SharingCookie;
立即从此共享(共享cookie cookie){
MallocGuard&ptr=cookie.first;
SharedPtr&shared=cookie.second;
//这一行包含实际逻辑:
共享。重置(重新解释
class a_class
{
public:
    a_class() : b( this ) {}
private:
    b_class b;
};
class a_class;
class b_class
{
  friend class a_class;
  a_class* mya;
  b_class(a_class*p)
  : mya(p) {}
public:
  virtual~b_class() {}   // required for unique_ptr<b_class> to work
  virtual void fiddle(); // do something to mya
};

class a_class
{
  std::unique_ptr<b_class> myb;
public:
  a_class()
  : myb(new b_class(this)) {}
  template<typename B>
  void change_myb()
  {
    myb.reset(new B(this));
  }
};
template <class Impl>
class ImmediatelySharedFromThis : public std::enable_shared_from_this<Impl> {
    typedef std::unique_ptr<void, std::function<void(void*)>> MallocGuard;
    typedef std::shared_ptr<Impl> SharedPtr;

    // disallow `new MyClass(...)`
    static void *operator new(size_t) = delete;
    static void *operator new[](size_t) = delete;
    static void operator delete[](void*) = delete;
protected:
    typedef std::pair<MallocGuard&, SharedPtr&> SharingCookie;

    ImmediatelySharedFromThis(SharingCookie cookie) {
        MallocGuard &ptr = cookie.first;
        SharedPtr &shared = cookie.second;
        // This single line contains the actual logic:
        shared.reset(reinterpret_cast<Impl*>(ptr.release()));
    }
public:
    // Create new instance and return a shared pointer to it.
    template <class ...Args>
    static SharedPtr create(Args &&...args) {
        // Make sure that the memory is free'd if ImmediatelySharedFromThis
        // is not the first base class, and the initialization
        // of another base class throws an exception.
        MallocGuard ptr(aligned_alloc(alignof(Impl), sizeof(Impl)), free);
        if (!ptr) {
            throw std::runtime_error("OOM");
        }

        SharedPtr result;
        ::new (ptr.get()) Impl(SharingCookie(ptr, result),
                               std::forward<Args>(args)...);
        return result;
    }

    static void operator delete(void *ptr) {
        free(ptr);
    }
};

class MyClass : public ImmediatelySharedFromThis<MyClass> {
    friend class ImmediatelySharedFromThis<MyClass>;

    MyClass(SharingCookie cookie, int some, int arguments) :
        ImmediatelySharedFromThis(cookie)
        // You can pass shared_from_this() to other base classes
    {
        // and you can use shared_from_this() in here, too.
    }
public:
    ....
};

...

std::shared_ptr<MyClass> obj = MyClass::create(47, 11); 
class MyClass: enable_shared_from_this<MyClass>
{
    public:
        //If you use this, you will die.
        MyClass(bool areYouBeingAnIdiot = true)
        {
            if (areYouBeingAnIdiot)
            {
                throw exception("Don't call this constructor! Use the Create function!");
            }

            //Can't/Don't use this or shared_from_this() here.
        }

        static shared_ptr<MyClass> Create()
        {
            shared_ptr<MyClass> myClass = make_shared<MyClass>(false);

            //Use myClass or myClass.get() here, now that it is created.

            return myClass;
        }
}

//Somewhere.
shared_ptr<MyClass> myClass = MyClass::Create();