Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > взаимодействие обычных указателей и shared


Автор: Alek86 12.11.2007, 19:48
у меня некоторое время уже пишется немелкая прога
и лишь сравнительно недавно я начал использовать boost::shared_ptr

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

Код

MyClass* pClass = new MyClass;
//...
Func1(pClass);
//...
delete pClass;


а вот теперь, как я понял преимущества shared_ptr, функции типа Func1 стали принимать shared_ptr'ы. И получилась ситуация:
Код

class MyClass {     // какой-то класс
public:
    int pI[100];
};
void Func1(MyClass* pMyClass) {    // старая функция
    // код
}
void Func2(boost::shared_ptr<MyClass> vMyClass) {    // новая функция, с бустом
    // код
}

int main() {
    // допустим, в моем старом коде нужно добавить новую функцию, которая реализована и
    // принимает shared_ptr
    MyClass* pMyClass = new MyClass;
    Func1(pMyClass);        // все в порядке
    Func2(boost::shared_ptr<MyClass>(pMyClass));   // shared_ptr удаляет "не свой" объект
    delete pMyClass;      // взрыв, хотя он тут быть как бы и не должон
    system("pause");
}


как бы это можно провернуть, чтобы работало?

Автор: JackYF 12.11.2007, 20:32
Цитата(Alek86 @  12.11.2007,  19:48 Найти цитируемый пост)
boost::shared_ptr<MyClass>(pMyClass)

Передаёшь локальную переменную, она уничтожается сейчас же, не гуд.

Цитата(Alek86 @  12.11.2007,  19:48 Найти цитируемый пост)
Func2(boost::shared_ptr<MyClass>(pMyClass));

Код


...
boost::shared_ptr<MyClass> ptrMyClass(pMyClass);
Func2(ptr);




Цитата(Alek86 @  12.11.2007,  19:48 Найти цитируемый пост)
void Func2(boost::shared_ptr<MyClass> vMyClass)

возможно, 
Код

void Func2(boost::shared_ptr<MyClass>& vMyClass)

Автор: Fazil6 12.11.2007, 20:39
Код

int main() {
     
    // допустим, в моем старом коде нужно добавить новую функцию, которая реализована и
    // принимает shared_ptr
    
    boost::shared_ptr<MyClass> pMyClass(new MyClass());

    Func1(pMyClass.get());        // старая функция
    Func2(pMyClass);                 // новая функция
    
    system("pause");
}

Автор: Alek86 12.11.2007, 21:31
в реале все чуток сложнее
 к примеру, так:
Код


class Class1 {
// ...
    void Func2(boost::shared_ptr<MyClass> vMyClass);
// ...
};
class Class2 {
// ...
    MyClass* m_MyClass;
// ...
    Func1() {
        Class1 vClass1;
        vClass1.Func2(boost::shared_ptr<MyClass>(m_MyClass))
    }
// ...
};


выход вижу в том, чтобы хранить рядом с
Код

MyClass* m_MyClass;

еще и 
Код

boost::shared_ptr<MyClass> m_MyClassSharedPtr // в конструкторе записать туда m_MyClass;


но, имхо, не очень удобно, так как надо следить за m_MyClass, чтобы  переназначать m_MyClassSharedPtr, когда m_MyClass меняется....

Добавлено @ 21:34
Fazil6, так бы я догадался, но дело в том, что код старый и работает - не хочется его весь менять

Добавлено через 3 минуты и 32 секунды
а, да, еще его МНОГО

Добавлено через 14 минут и 57 секунд
Цитата(JackYF @  12.11.2007,  20:32 Найти цитируемый пост)
void Func2(boost::shared_ptr<MyClass>& vMyClass)

зачем указатель передавать по ссылке?

Автор: JackYF 12.11.2007, 22:06
Цитата(Alek86 @  12.11.2007,  21:31 Найти цитируемый пост)
зачем указатель передавать по ссылке?

это так, на пробу. Возможно, и незачем.

Автор: Fazil6 12.11.2007, 23:44
Цитата(Alek86 @  12.11.2007,  21:31 Найти цитируемый пост)
выход вижу в том, чтобы хранить рядом с


Цитата(Alek86 @  12.11.2007,  21:31 Найти цитируемый пост)
еще и 

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

Код

MyClass* m_MyClass;


заменить на
Код

typedef boost::shared_ptr<MyClass> MyClass_t;

MyClass_t  m_MyClass(new .... );

дальше компилятор скажет где исправить (выкинуть delete и в аргументах). Использование m_MyClass как указателя никак не изменится с изменением на shared_ptr
Но, если стоит выбор между альтернативами, нужно остановиться на чем-то одном. На 2-х стульях тяжело усидеть.

Автор: Alek86 12.11.2007, 23:54
неужели так мало у кого такие проблемы возникали, что при проектировании shared_ptr не учли возможность такой поддержки старого кода? :(

Автор: JackYF 13.11.2007, 00:14
Цитата(Alek86 @  12.11.2007,  23:54 Найти цитируемый пост)
не учли возможность такой поддержки старого кода? :( 

старый код надо заменять, а не поддерживать. Будет у тебя такой бааальшой патч к проекту, состоящий из кучи вот таких вот маленьких замен.

Цитата(Fazil6 @  12.11.2007,  23:44 Найти цитируемый пост)
заколебешься пыль глотать потом. 
Это будет несопровождаемо. 
Пользуйся либо одним, либо другим 

ППКС.

Автор: Alek86 13.11.2007, 00:27
Цитата(JackYF @  13.11.2007,  00:14 Найти цитируемый пост)
ППКС.

?


Цитата(JackYF @  13.11.2007,  00:14 Найти цитируемый пост)
старый код надо заменять, а не поддерживать.

 smile 
это скажи Страуструпу smile
вообще весь С++ на том и держится, что старый код менять сильно не нужно

Автор: Fazil6 13.11.2007, 00:52
Цитата(Alek86 @  13.11.2007,  00:27 Найти цитируемый пост)
вообще весь С++ на том и держится, что старый код менять сильно не нужно

так ты же сильно хочешь его менять... Рассмотри еще вариант расширения интерфейса, в котором используется буст чтобы он мог принимать указатель, чтобы его можно было использовать в старом коде не переделывая ничего в этом старом коде

Цитата(Alek86 @  12.11.2007,  23:54 Найти цитируемый пост)
неужели так мало у кого такие проблемы возникали, что при проектировании shared_ptr не учли возможность такой поддержки старого кода? :(

какой такой? Чтобы деструктор shared_ptr не вызывал delete ? Нахрен он тогда нужен?
Все, что надо там учли.

Автор: Lazin 13.11.2007, 08:40
Если старая функция не сохраняет указатель на объект и не пытается его удалить, то можно ее оставить до поры до времени. Но если старая ф-я гденибудь сохранит указатель на объект, то возможна ситуация когда этот указатель проживет дольше чем все shared_ptr-ы на тот-же объект и если программа попробует к нему обратица, то будет AV (aka segfault). Так-что как уже здесь не раз сказали проще исправить все функции.
До использования shared_ptr я использовал свой велосипед, базовый класс поддерживал подсчет ссылок, а его  деструктор был защищенным. Благодаря этому нельзя было создать такой объект в стеке. Класс указателя который работал с моим указателем был объявлен другом, короче в результате работать с такими объектами возможно только через мою версию смарт-поинтера, и это спасало от многих ошибок

Автор: archimed7592 14.11.2007, 02:07
Извините, если прерву ваш спор ни о чём, но изначальная проблема решается элементарно - достаточно взглянуть на описание класса shared_ptr(можно даже не читать - просто взглянуть).

Код


struct dummy_deleter
{
    void operator()(void *)
    { }
};

int main() {
    // допустим, в моем старом коде нужно добавить новую функцию, которая реализована и
    // принимает shared_ptr
    MyClass* pMyClass = new MyClass;
    Func1(pMyClass);        // все в порядке
    Func2(boost::shared_ptr<MyClass>(pMyClass, dummy_deleter()));   // shared_ptr удаляет "не свой" объект
    delete pMyClass;      // взрыв, хотя он тут быть как бы и не должон
    system("pause");
}

Автор: Alek86 14.11.2007, 17:06
Цитата(archimed7592 @  14.11.2007,  02:07 Найти цитируемый пост)
Извините, если прерву ваш спор ни о чём, но изначальная проблема решается элементарно - достаточно взглянуть на описание класса shared_ptr(можно даже не читать - просто взглянуть).


гы, пепец я внимательный smile
спасибо

Автор: archimed7592 14.11.2007, 17:35
Кстати, если уж часто этим пользоваться, то я бы сделал так:
Код

template< class T >
boost::shared_ptr< T > wrap_dumb_ptr(T *ptr)
{
    struct dummy_deleter
    {
        void operator()(T *)
        { }
    };
    return boost::shared_ptr< T >(ptr, dummy_deleter());
}

Автор: Alek86 14.11.2007, 18:10
тогда вопрос вдогонку
такой, что, типа, лень самому искать, так что не матюкайтьесь, плиз smile

есть стандартный функтор, что ничего не делает?

Добавлено через 1 минуту и 39 секунд
ЗЫ. скорее всего нету, но "а вдруг?"

Автор: archimed7592 14.11.2007, 18:13
Нету smile.
Ибо толку от него - 0... Нужно же, помимо факта "ничего не делает", указать, какие аргументы принимает, какой тип возвращаемого значения, если тип не void, то что возвращать?

Автор: Alek86 14.11.2007, 18:27
ну, для заглушки...
принимать (...), возвращать boost::any

(знаю, невыполнимо smile )

ладно, чтоб тема не переросла в ляля, предлагаю пометить решенной smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)