Повышение умных указателей: я могу выразить это более кратким способом? - PullRequest
0 голосов
/ 04 апреля 2011

сегодня я работаю с Boost :: shared_ptr, и у меня есть вопрос.

vector<shared_ptr<KlasaA> > vec;
vec.push_back(shared_ptr<KlasaA>(new KlasaB));
vec.push_back(shared_ptr<KlasaA>(new KlasaC));
vec.push_back(shared_ptr<KlasaA>(new KlasaC));
vec.push_back(shared_ptr<KlasaA>(new KlasaA));

for (vector<shared_ptr<KlasaA> >::const_iterator c_it = vec.begin();
    c_it != vec.end(); ++c_it)
{
    cout << c_it->get()->foo(10) << endl;
}

Цикл выше проходит через вектор и полиморфно вызывает foo(10).

Мой вопрос:

Может ...

for (vector<shared_ptr<KlasaA> >::const_iterator c_it = vec.begin();
    c_it != vec.end(); ++c_it)

и

cout << c_it->get()->foo(10) << endl;

быть выражено более кратко? Заранее спасибо.

Ответы [ 5 ]

6 голосов
/ 04 апреля 2011
typedef boost::shared_ptr<KlasaA> SharedKlasaA;
typedef vector<SharedKlasaA> KlasaAVector;

KlasaAVector vec;
vec.push_back(SharedKlasaA(new KlasaB));
...
for (KlasaAVector::const_iterator ...

cout << (*c_it)->foo(10);
3 голосов
/ 04 апреля 2011

shared_ptr имеет неявный конструктор downcast, поэтому вы можете написать

vec.push_back(shared_ptr<KlasaB>(new KlasaB));

Обратите внимание, что тип shared_ptr равен shared_ptr<KlasaB>, а vec ожидает shared_ptr<KlasaA>.

.Имейте в виду, вы можете заменить конструктор shared_ptr на вызов функции make_shared (который в любом случае может быть предпочтительным).

vec.push_back(make_shared<KlasaB>());

Это избавит вас от необходимости набирать кучу имен классов.make_shared принимает аргументы, которые он передает, поэтому make_shared<X> является хорошей заменой для new X.

Вы можете заметить, что здесь есть потенциальные последствия для производительности: структура данных make_shared может (будет?), и есть дополнительное неявное преобразование, но оно может быть оптимизировано компилятором.Профиль и проверка.

3 голосов
/ 04 апреля 2011

Вы можете использовать библиотеку Boost.Foreach.Тогда это будет выглядеть довольно лаконично и ясно:

BOOST_FOREACH( boost::shared_ptr<KlasaA> v, vec )
{
    std::cout << v->foo(10) << std::endl;
}
3 голосов
/ 04 апреля 2011

Насколько я вижу, инициализация вашего итератора кажется настолько компактной, насколько это возможно. Если вы действительно хотите, вы можете написать функцию цикла как:

cout << (*c_it)->foo(10) << endl;

Это сохраняет только 4 символа, но выглядит немного яснее.

0 голосов
/ 04 апреля 2011

В зависимости от компилятора вы можете делать такие вещи:

std::foreach(vec.begin(),vec.end(),[](const boost::shared_ptr<KlasaA> &p){
  cout<<p->foo(10);
});
...