Вопросы по использованию shared ptr-c++
у меня есть несколько вопросов о наилучшей практике использования shared_ptr
.
Вопрос 1
копирование shared_ptr
дешевые? Или мне нужно передать его как ссылку на мои собственные вспомогательные функции и возвращать как значение? Что-то вроде
void init_fields(boost::shared_ptr<foo>& /*p_foo*/);
void init_other_fields(boost::shared_ptr<foo>& /*p_foo*/);
boost::shared_ptr<foo> create_foo()
{
boost::shared_ptr<foo> p_foo(new foo);
init_fields(p_foo);
init_other_fields(p_foo);
}
Вопрос 2
должен ли я использовать boost::make_shared
построить shared_ptr
? Если да, то какие преимущества он дает? И как мы можем использовать make_shared
, когда T
нет конструктор без параметров?
Вопрос 3
как использовать const foo*
? Для этого я нашел два подхода.
void take_const_foo(const foo* pfoo)
{
}
int main()
{
boost::shared_ptr<foo> pfoo(new foo);
take_const_foo(pfoo.get());
return 0;
}
или
typedef boost::shared_ptr<foo> p_foo;
typedef const boost::shared_ptr<const foo> const_p_foo;
void take_const_foo(const_p_foo pfoo)
{
}
int main()
{
boost::shared_ptr<foo> pfoo(new foo);
take_const_foo(pfoo);
return 0;
}
Вопрос 4
как я могу вернуться и проверить для NULL
на
5 ответов
на большинство вопросов были даны ответы, но я не согласен с тем, что копия shared_ptr дешева.
копия различная семантика из ссылки pass-by-reference. Он изменит счетчик ссылок, который вызовет атомарный приращение в лучшем случае и блокировку в худшем случае. Вы должны решить, какая семантика вам нужна, и тогда вы будете знать, передавать ли по ссылке или по значению.
с точки зрения производительности, это гораздо лучше чтобы использовать контейнер указателя boost вместо контейнера shared_ptr.
копирование дешево, указатель не занимает много места. Весь смысл в том, чтобы сделать его маленьким, чтобы разрешить использование в контейнерах по значению (например,
std::vector< shared_ptr<Foo> >
).make_shared
принимает переменное количество параметров, и является предпочтительным mechanicsm над созданием его самостоятельно (просто какmake_pair
). Преимуществом является читаемость, особенно если задействованы временные и/или пространства имен:boost:: const_ptr_cast как уже предлагалось
интеллектуальные указатели имеют перегруженные операторы и могут непосредственно использоваться в выражениях, вычисляемых для bool. Не используйте
get
. За что угодно. Вместо сравненияp.get
ни к чему, сравните пустой экземпляр указателя (my_ptr != boost::shared_ptr< MyClass >()
)
объявление.2
func_shared( boost::shared_ptr<my_tools::MyLongNamedClass>(
new my_tools::MyLongNamedClass( param1, param2 ) );
и
func_shared( boost::make_shared<my_tools::MyLongNamedClass>( param1, param2 ));
- да, копия абсолютно дешевая. Помимо удержания указателя, есть (обычно) еще один член данных для класса shared_ptr - счетчик использования.
- Не могу ответить на этот вопрос, я обычно использую версии boost до появления make_shared (1.40?)
- используйте boost:: const_pointer_cast
- shared_ptr есть оператор==/!= определенный. В приведенном выше примере: if (f)
копирование shared_ptr теперь стоит 32 байта в копии стека и дополнительных приращениях/уменьшениях refcount. Решите, дешево ли это для вас или нет, но я не вижу причин, почему бы не передать ссылку const, тем более, что у вас уже есть typedef для ptr:
void f(const foo_ptr &myfoo)
особенно учитывая, что стандартный параметр no-write-permissions, передаваемый в C++, является ссылкой const.Я бы предпочел не иметь функций, которые принимают указатель, который не является общим. Это похоже (хотя и не идентично) на семантику передачи параметров в Java и C#. Зачем погружаться в решение каждый раз, как передать объект, вместо того, чтобы иметь один стандартный способ сделать это?
использовать
if(p)
как и для обычных указателей. Семантика преобразования boolean довольно аккуратна.
- одна из основных причин существования shared_ptr должна быть относительно дешевой для копирования.
- существуют версии make_shared, которые принимают параметры (и если ваш компилятор поддерживает variadic шаблоны, тот, который принимает список переменных параметров).
- похоже, вы ищете const_ptr_cast?
- чтобы вернуть нулевой указатель, вы можете передать' 0 ' в share_ptr ctor. Для проверки на нулевой указатель, можно сравнить С. получить() в 0.