инициализация общего указателя статическим или глобальным объектом - PullRequest
0 голосов
/ 01 декабря 2018

Следующий код показывает, что инициализация общего объекта с адресом глобального или статического объекта неверна, так как глобальный объект удаляется, когда общий указатель выходит из области видимости.

class Dog() {
public:
    void bark() {
        cout << "Dog barks" << endl;
    }
};
Dog g_Dog;
void test() {
    shared_ptr<Dog> myDog(&g_Dog);
    myDog->bark();
}
int main() {

    test();

}

Вышеприведенный код вылетает.Насколько я понимаю, мы не должны инициализировать общие указатели со статическим или глобальным объектом и должны делать это только с объектами в куче.Это правильно?

Я видел следующий фрагмент кода в руководстве по буст-логу (https://www.boost.org/doc/libs/develop/libs/log/doc/html/log/tutorial/sinks.html)

#include <boost/core/null_deleter.hpp>

// We have to provide an empty deleter to avoid destroying the global stream object
boost::shared_ptr< std::ostream > stream(&std::clog, boost::null_deleter());
sink->locked_backend()->add_stream(stream);

Не могли бы вы, ребята, объяснить, почему код

  boost::shared_ptr< std::ostream > stream(&std::clog, boost::null_deleter()); 

не делаетвызвать какие-либо проблемы. Похоже, что std :: clog является глональной или статической переменной. Не так ли? Почему это не создает риск быть уничтоженным, когда вышеуказанный общий указатель потока выходит из области видимости. Пожалуйста, пролите светСпасибо

Ответы [ 3 ]

0 голосов
/ 01 декабря 2018

Это законно, если вы предоставите средство удаления, которое не будет пытаться уничтожить и освободить его.

shared_ptr принимает два аргумента (см. Документацию ): адрес и средство удаления.Аргумент Deleter является необязательным.

Удалитель по умолчанию (т. Е. Тот, который используется, если вы явно не предоставили ничего) уничтожает объект и освобождает кучу, поэтому он, очевидно, не будет работать ни с чем, не находящимся в куче.

0 голосов
/ 01 декабря 2018

Существует два варианта:

  1. Использовать nop-delete.Просто примите служебные данные этого ложного блока управления.

  2. Используйте конструктор псевдонимов.std::weak_ptr s не будет работать с ним.
    См. " Использование конструктора псевдонимов общего указателя C ++ с пустым общим указателем ".

0 голосов
/ 01 декабря 2018

По ссылке null_deleter : функциональный объект boost :: null_deleter можно использовать в качестве средства удаления с интеллектуальными указателями, такими как unique_ptr или shared_ptr.Удалитель ничего не делает с указателем, предоставленным при освобождении, что делает его полезным, когда указанный объект освобождается в другом месте.

Другими словами, используя null_deleter, интеллектуальный указатель никогда не будет пытаться удалить указанныйобъект.

...