почему нет boost::make_shared_ptr ?
От: rg45 СССР  
Дата: 14.03.06 12:36
Оценка: +1
Меня удивляет, что в бусте нет такой функции:
namespace boost{
template<typename T>
shared_ptr<T> make_shared_ptr(T * t)
{
  return shared_ptr<T>(t);
}
}//namespace boost


По аналогии с boost::make_tuple или std::make_pair.
Может быть есть веские причины, по которым эту функцию не стали делать?
Posted via RSDN NNTP Server 1.9
--
Справедливость выше закона. А человечность выше справедливости.
Re: почему нет boost::make_shared_ptr ?
От: ArtDenis Россия  
Дата: 14.03.06 12:51
Оценка:
Думаю, потому, что для умного указателя привычнее писать
ptr.reset(new SomeClass);

чем
ptr = boost::make_shared_ptr(new SomeClass);
Posted via RSDN NNTP Server 2.0
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[2]: почему нет boost::make_shared_ptr ?
От: rg45 СССР  
Дата: 14.03.06 13:05
Оценка:
"ArtDenis" <15178@users.rsdn.ru> wrote in message news:1781646@news.rsdn.ru...
> Думаю, потому, что для умного указателя привычнее писать
>
> ptr.reset(new SomeClass);
>

> чем
>
> ptr = boost::make_shared_ptr(new SomeClass);
>


Не та немножко ситуация: переменной ptr не существует, а существует функция, принимающая boost::shared_ptr. Точнее говоря, функций, принимающих boost::shared_ptr, различных типов множество. И каждый раз, чтоб вызвать такую функцию приходится писать что то вроде этого:
    some_func(boost::shared_ptr<SomeObj<SomeT1, SomeT2> >(obj_ptr));

вместо этого:
    some_func(boost::make_shared_ptr(obj_ptr));
Posted via RSDN NNTP Server 1.9
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: почему нет boost::make_shared_ptr ?
От: Tom Россия http://www.RSDN.ru
Дата: 14.03.06 13:10
Оценка:
R>
R>    some_func(boost::shared_ptr<SomeObj<SomeT1, SomeT2> >(obj_ptr));
R>

а может функций с такой сигнатурой писать нестоит?
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re[3]: почему нет boost::make_shared_ptr ?
От: ArtDenis Россия  
Дата: 14.03.06 13:16
Оценка:
rg45 пишет:
> Не та немножко ситуация: переменной ptr не существует, а существует функция, принимающая boost::shared_ptr. Точнее говоря, функций, принимающих boost::shared_ptr, различных типов множество. И каждый раз, чтоб вызвать такую функцию приходится писать что то вроде этого:

Ну... Ради такого редкого случая ф-цию make_shared_ptr можно написать
самостоятельно Не думаю, что она была бы полезна в общем случае.
Posted via RSDN NNTP Server 2.0
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[4]: почему нет boost::make_shared_ptr ?
От: rg45 СССР  
Дата: 14.03.06 13:20
Оценка:
"Tom" <3627@users.rsdn.ru> wrote in message news:1781722@news.rsdn.ru...
> R>
> R>    some_func(boost::shared_ptr<SomeObj<SomeT1, SomeT2> >(obj_ptr));
> R>

> а может функций с такой сигнатурой писать нестоит?

Ну это вопрос более сложный.
Во-первых, от упрощения сигнатуры может усложниться реализация.
Во-вторых, в данном примере сигнатура может быть самой простой, например такой:
    void some_func(boost::shared_ptr<BasicObj>);

тогда встает дилемма: либо писать сложную конструкцию, типа той, что я написал, либо для каждого кокретного класса держать в голове его базовый класс.
В-третьх, не всегда есть возможность эту сигнатуру изменить, она может быть интерфейсом "чужой" библиотеки.
Posted via RSDN NNTP Server 1.9
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: почему нет boost::make_shared_ptr ?
От: rg45 СССР  
Дата: 14.03.06 13:27
Оценка:
"ArtDenis" <15178@users.rsdn.ru> wrote in message news:1781749@news.rsdn.ru...
> Ну... Ради такого редкого случая ф-цию make_shared_ptr можно написать
> самостоятельно Не думаю, что она была бы полезна в общем случае.

Да так оно и есть, но тогда это выглядит так, будто я пишу расширение к бусту.
А потом, мне интересен вот какой момент: реализация этой функции, как мне кажется, была бы вполне естественной в бусте, но ее там нет, может я что то упускаю из виду?
Posted via RSDN NNTP Server 1.9
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: почему нет boost::make_shared_ptr ?
От: einstein  
Дата: 14.03.06 14:44
Оценка:
Здравствуйте, rg45, Вы писали:



R>Не та немножко ситуация: переменной ptr не существует, а существует функция, принимающая boost::shared_ptr. Точнее говоря, функций, принимающих boost::shared_ptr, различных типов множество. И каждый раз, чтоб вызвать такую функцию приходится писать что то вроде этого:

R>
R>    some_func(boost::shared_ptr<SomeObj<SomeT1, SomeT2> >(obj_ptr));
R>

R>вместо этого:
R>
R>    some_func(boost::make_shared_ptr(obj_ptr));
R>


не совсем понятно почему вы используете указатель на уже существующий объект obj_ptr вместо создания нового с помощью оператора new?

Вообще то данный подход не совсем верен.
Во-первых до вызова some_func (boost::shared_ptr<T>(obj_ptr)) где obj_ptr типа T*
создается новый объект shared_ptr который принимает владение объектом и будет уничтожать его с помощью стандартного deleter'a. И при уничтожении этого объекта shared_ptr удалится и владеемый им объект типа T*
То есть после вышупомянутого вызова obj_ptr будет указывать на несуществующую область памяти.
Вообще в вашем случае есть такие варианты вызова:


some_func (boost::shared_ptr<T>(new T() ));

boost::shared_ptr<T> t(new T());
some_func (t)


В первом случае вам самим не нужен объект T, а во втором — он вам нужен после вызова some_func.
Но в первом случае могут возникнуть проблемы если нужно передать несколько указателей:

some_func (boost::shared_ptr<T1>(new T1() ), boost::shared_ptr<T2>(new T2() );


При этом если возникнет исключение в одном из консткруторов T1 или T2, то произойдет утечка памяти. (порядок вызова этих конструкторов не определен по стандарту)
Re[5]: почему нет boost::make_shared_ptr ?
От: Tom Россия http://www.RSDN.ru
Дата: 14.03.06 14:56
Оценка:
Здравствуйте, rg45, Вы писали:


R>"Tom" <3627@users.rsdn.ru> wrote in message news:1781722@news.rsdn.ru...

>> R>
>> R>    some_func(boost::shared_ptr<SomeObj<SomeT1, SomeT2> >(obj_ptr));
>> R>

>> а может функций с такой сигнатурой писать нестоит?

R>Ну это вопрос более сложный.

R>Во-первых, от упрощения сигнатуры может усложниться реализация.
R>Во-вторых, в данном примере сигнатура может быть самой простой, например такой:
R>
R>    void some_func(boost::shared_ptr<BasicObj>);
R>

R>тогда встает дилемма: либо писать сложную конструкцию, типа той, что я написал, либо для каждого кокретного класса держать в голове его базовый класс.
R>В-третьх, не всегда есть возможность эту сигнатуру изменить, она может быть интерфейсом "чужой" библиотеки.

Да нет же, суть в том, что стоит ли вообще в сигнатуру выность boost::shared_ptr
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re[4]: почему нет boost::make_shared_ptr ?
От: rg45 СССР  
Дата: 14.03.06 16:31
Оценка:
"einstein" <23471@users.rsdn.ru> wrote in message news:1782110@news.rsdn.ru...
E> не совсем понятно почему вы используете указатель на уже существующий объект obj_ptr вместо создания нового с помощью оператора new?
E>...

Т.о. можно сделать такой вывод: практика, когда объект создается, после этого с ним выполняются нектороые операции, пользуясь "голым" указателем, а только потом этот указатель помещается в shared_ptr является неправильной. И чтобы не способствовать этому, упомянутой функции просто не существует.
Правильно?
Posted via RSDN NNTP Server 1.9
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: почему нет boost::make_shared_ptr ?
От: remark Россия http://www.1024cores.net/
Дата: 14.03.06 17:49
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Да нет же, суть в том, что стоит ли вообще в сигнатуру выность boost::shared_ptr



Почему? А что принимать? Обычный указатель?



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: почему нет boost::make_shared_ptr ?
От: kan_izh Великобритания  
Дата: 14.03.06 19:55
Оценка: +1
einstein wrote:

...
> При этом если возникнет исключение в одном из консткруторов T1 или T2,
> то произойдет утечка памяти. (порядок вызова этих конструкторов не
> определен по стандарту)
Я вот тоже не понял.

В чём принципиальная разница между
func(make_shared_ptr(new A));
и
func(shared_ptr<A>(new A));
?

Какие могут быть ошибки? В каких случаях первый код опаснее второго?
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[7]: почему нет boost::make_shared_ptr ?
От: Tom Россия http://www.RSDN.ru
Дата: 14.03.06 22:14
Оценка:
R>Почему? А что принимать? Обычный указатель?
R>

конечно, смысл в создании shared_pointer-а в том, что бы продлить жизнь контролируемого обьекта, а зачем его указыать в сигнатуре функции, если, по идее, тот, кто передаёт указатель в функцию всё равно держит ссылку на обьект. На мой взгляд shared_pointer стоит использовать для хранения обьектов в полях структур либо контейнерах.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re[8]: почему нет boost::make_shared_ptr ?
От: nau  
Дата: 15.03.06 00:22
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>конечно, смысл в создании shared_pointer-а в том, что бы продлить жизнь контролируемого обьекта, а зачем его указыать в сигнатуре функции, если, по идее, тот, кто передаёт указатель в функцию всё равно держит ссылку на обьект. На мой взгляд shared_pointer стоит использовать для хранения обьектов в полях структур либо контейнерах.


Это конечно все правильно. Но как поступать в случаях передачи владения указателем функцией? Т.е.
в функции создается объект, с ним выполняются определенные действия и его нужно вернуть в вызывающую функцию. Создавать объект снаружи не предлагать, допустим функция создает одного из наследников, а возвращает базовый указатель.
В теории практика не отличается от теории, но на практике — отличается
Re[5]: почему нет boost::make_shared_ptr ?
От: alexeiz  
Дата: 15.03.06 03:49
Оценка:
Здравствуйте, rg45, Вы писали:

R>Т.о. можно сделать такой вывод: практика, когда объект создается, после этого с ним выполняются нектороые операции, пользуясь "голым" указателем, а только потом этот указатель помещается в shared_ptr является неправильной. И чтобы не способствовать этому, упомянутой функции просто не существует.

R>Правильно?

Правильно.

В добавок приведу пример, когда не избежать ситуации с созданием shared_ptr из голого указателя.
struct A {
    void foo();
};

void bar(shared_ptr<A>);

void A::foo() {
   bar(shared_ptr<A>(this));   // bug!
}

int main()
{
    shared_ptr<A> obj(new A());
    obj->foo();
    // obj destructor crashes in operator delete
}

Баг в том, что создаётся два разных shared_ptr для одного и того же голого указателя. Проблема решается применением enable_shared_from_this:
struct A : boost::enable_shared_from_this<A> {...};
void A::foo() {
    bar(shared_from_this());  // shared_from_this() is inherited from enable_shared_from_this
}

shared_from_this создаёт shared_ptr, использующий тот-же счётчик ссылок что и первоначальный shared_ptr<A> obj(new A()).
Re[8]: почему нет boost::make_shared_ptr ?
От: remark Россия http://www.1024cores.net/
Дата: 15.03.06 08:46
Оценка: +1
Здравствуйте, Tom, Вы писали:

R>>Почему? А что принимать? Обычный указатель?

R>>

Tom>конечно, смысл в создании shared_pointer-а в том, что бы продлить жизнь контролируемого обьекта, а зачем его указыать в сигнатуре функции, если, по идее, тот, кто передаёт указатель в функцию всё равно держит ссылку на обьект. На мой взгляд shared_pointer стоит использовать для хранения обьектов в полях структур либо контейнерах.



Не согласен! Если речь идёт о такой ситуации, то зачем тогда вообще передавать указатель? Тут можно передавать ссылку — со ссылкой всё понятно — с ней владение не передашь. Или boost::weak_ptr.

Чаще в такой ситуации имеется в виду передача владения. А вот это уже неправильно — захватывать объект в shared_ptr внутри функции — это надо делать вне функции, а функция должна принимать уже shared_ptr.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: почему нет boost::make_shared_ptr ?
От: Tom Россия http://www.RSDN.ru
Дата: 15.03.06 08:54
Оценка:
nau>Это конечно все правильно. Но как поступать в случаях передачи владения указателем функцией? Т.е.
nau>в функции создается объект, с ним выполняются определенные действия и его нужно вернуть в вызывающую функцию. Создавать объект снаружи не предлагать, допустим функция создает одного из наследников, а возвращает базовый указатель.

Согласен, бывает так, конечно в таком случае нужно возвращать шаред ptr. Я вообще предпочитаю пользоваться интрузив птр-ом
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Народная мудрось
всем все никому ничего(с).
Re: почему нет boost::make_shared_ptr ?
От: remark Россия http://www.1024cores.net/
Дата: 15.03.06 09:01
Оценка:
Здравствуйте, rg45, Вы писали:

R>Меня удивляет, что в бусте нет такой функции:

R>
R>namespace boost{
R>template<typename T>
R>shared_ptr<T> make_shared_ptr(T * t)
R>{
R>  return shared_ptr<T>(t);
R>}
R>}//namespace boost
R>


R>По аналогии с boost::make_tuple или std::make_pair.

R>Может быть есть веские причины, по которым эту функцию не стали делать?


Ещё одна проблема есть, которую вроде никто не упоминал. Одна из причин использования динамических объектов — динамический полиморфизм. Поэтому зачастую в сигнатуре функции написано shared_ptr<ISomeInterface>, а ты в функцию передаёшь SomeInterfaceImpl*. Преобразование указателя из SomeInterfaceImpl* в ISomeInterface* иногда надо контролировать. Для чего в shared_ptr есть не только:

    template<class Y>
    shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws


Но и:

    template<class Y>
    shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)

    template<class Y>
    shared_ptr(shared_ptr<Y> const & r, detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)

    template<class Y>
    shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)

    template<class Y>
    shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)


Так вот к этим функциям ты не получишь доступ, если будешь использовать make_shared_ptr.



Обычно я делаю просто вот так, и получается терпимо:

typedef boost::shared_ptr<IInterface> IInterfacePtr;
someFunc(IInterfacePtr(p));





1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: почему нет boost::make_shared_ptr ?
От: remark Россия http://www.1024cores.net/
Дата: 15.03.06 09:04
Оценка:
Здравствуйте, rg45, Вы писали:

R>Меня удивляет, что в бусте нет такой функции:

R>
R>namespace boost{
R>template<typename T>
R>shared_ptr<T> make_shared_ptr(T * t)
R>{
R>  return shared_ptr<T>(t);
R>}
R>}//namespace boost
R>


R>По аналогии с boost::make_tuple или std::make_pair.

R>Может быть есть веские причины, по которым эту функцию не стали делать?



Кстати, вроде никто не упоминал это (см. shared_new)
Так, что не всё так плохо



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: почему нет boost::make_shared_ptr ?
От: einstein  
Дата: 15.03.06 09:15
Оценка:
Здравствуйте, kan_izh, Вы писали:

_>Я вот тоже не понял.


_>В чём принципиальная разница между

_>func(make_shared_ptr(new A));
_>и
_>func(shared_ptr<A>(new A));
_>?

_>Какие могут быть ошибки? В каких случаях первый код опаснее второго?


Давайте по полочкам разложим вызов.

вы определяете make_shared_ptr как:

template<typename T>
shared_ptr<T> make_shared_ptr(T * t)
{
  return shared_ptr<T>(t); (1)
}



Во-первых, как я понимаю, вы хотите использотвать эту ф-цию, чтобы лишний раз не писать тип T и чтобы он выводился автоматически (т.к. шаблонные ф-ции позволяют это делать)

Давайте проанализируем что происходит при вызове func(make_shared_ptr(new A)) ?
Создается новый объект A в куче, передается ф-ции, она инициализирует в строке (1) временный объект типа shared_ptr<T> значением этого указателя и, таким образом принимает владение этим объектом. Счетчик ссылок при этом устанавливается равным 1. Далее при возврате из ф-ции происходит копирование этого временного объекта в другой временный объект shared_ptr<T> (который уже потом передается func, возможно опять с дополнительным копированием). При копировании с помощью конструктора копирования shared_ptr счетчик ссылок увеличивается и становится 2, далее после выхода из области видимости первого объекта он опять становится равным единице.

Я привел пример где удобство записи вполне может обернутся неоправданным уменьшением производительности (особенно в многопоточных приложениях, где обращение к счетчику ссылок возможно нуждается в исп. объектов синхронизации).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.