Слабый указатель на это в конструкторе

Я понимаю, что невозможно получить shared_ptr, вызвав shared_from_this() из конструктора класса, так как объект еще не создан. Однако возможно ли получить weak_ptr для объекта из конструктора? В некоторых сообщениях форума Boost, в которых обсуждается метод «weak_from_raw()», предполагается, что это возможно.

Изменить: Форма Boost обсуждает weak_from_raw http://lists.boost.org/boost-users/2010/08/61541.php


person tgoodhart    schedule 04.01.2011    source источник
comment
Вы можете опубликовать ссылку на сообщения форума, в которых обсуждается weak_from_raw()?   -  person Sam Miller    schedule 05.01.2011
comment
Не думайте, что weak_ptr хранит слабую ссылку на объект, которым уже управляет shared_ptr.   -  person ronag    schedule 05.01.2011
comment
@Sam groups.google.com/group/ буст-список/browse_thread/thread/   -  person James    schedule 05.01.2011


Ответы (2)


Я думаю, что вы ссылаетесь на это. Который, похоже, не был объединен с выпуском Boost (может быть, это неправильно).

Из документов по ускорению:

Часто задаваемые вопросы

Вопрос. Может ли объект создать для себя weak_ptr в своем конструкторе?

О. Нет. weak_ptr может быть создан только из shared_ptr, и во время создания объекта shared_ptr для объекта еще не существует. Даже если бы вы могли создать для этого временный shared_ptr, он вышел бы за пределы области действия в конце конструктора, и все экземпляры weak_ptr мгновенно истекли бы.

Решение состоит в том, чтобы сделать конструктор закрытым и предоставить фабричную функцию, которая возвращает shared_ptr:

class X
{
private:

    X();

public:

    static shared_ptr<X> create()
    {
        shared_ptr<X> px(new X);
        // create weak pointers from px here
        return px;
    }
};
person James    schedule 04.01.2011
comment
Спасибо за ответ, это было полезно для меня. Я получил редактирование, отклоненное за добавление отсутствующих скобок, поэтому вы можете сделать это самостоятельно :-) - person PhilLab; 28.08.2017
comment
Отсутствующих квадратных скобок нет ;) new X по умолчанию инициализирует экземпляр X. Вместо этого добавление круглых скобок делает его инициализированным напрямую (см. en.cppreference.com/w/cpp/language/new) - person James; 30.08.2017

См.: http://boost.org/doc/libs/1_42_0/libs/smart_ptr/sp_techniques.html#in_constructor

Проблема не в том, что объект не построен. Проблема в том, что shared_ptr не был создан. Если бы все, что вам нужно было сделать, это создать shared_ptr и отправить его куда-нибудь, все было бы в порядке. Это когда вы пытаетесь создать shared_ptr, содержащий только что созданный объект. Нет никакого способа соединить их, и поэтому у вас есть большая проблема.

Способ, которым работает shared_from_this, заключается в том, что он ожидает, что вы поместите объект как shared_ptr, прежде чем когда-либо вызовите shared_from_this, чтобы получить к нему доступ. Поскольку вы еще этого не сделали, так как конструктор объекта еще не завершен и, таким образом, shared_ptr не подключен к нему, вы не можете вызвать shared_from_this.

У вас будет точно такая же проблема со weak_ptr.

Итак, другими словами, эта абсурдная конструкция будет работать:

struct absurd
{
  absurd()
  {
    register(shared_ptr<absurd>(this));
  }
};

...
new absurd; // better not assign to a shared_ptr!!!

Но ты действительно не хочешь этого делать.

person Edward Strange    schedule 04.01.2011