2016-05-28 4 views
3

У меня есть небольшой сегмент кода, который мне нужно оптимизировать. Тема 'A' создала boost shared_ptr для объекта кучи. Thread 'A' записывает shared_ptr в очередь с потоком. Thread 'B' читает shared_ptr, использует его, а затем уничтожает.Создайте псевдонимы для boost :: shared_ptr через ссылку

Интенсивное профилирование/тестирование доказывает, что копирование shared_ptr, входящее/выходящее из очереди и корректирующее количество ссылок, является дорогостоящим. Поэтому я хотел бы передать общий ptr в очередь через ссылку. Я также хотел бы использовать std :: move для перемещения shared_ptr в очередь, а не для создания нового shared_ptr (я знаю, что это приведет к аннулированию параметра shared_ptr, который был передан в очередь).

Все описанное прекрасно работает, пока я не смешаюсь в тире полиморфизма. Я не могу передать ref_ shared_ptr производному obj функции, ожидающей shared_ptr в базовый класс. Я сварил это до очень маленького среза, который разоблачает поведение, которое меня смущает.

#include <boost/shared_ptr.hpp> 

class Base 
{ 
}; 

class Derived : public Base 
{ 
}; 

int main() 
{ 
    boost::shared_ptr<Derived> pDerived(new Derived()); // simple creation 
    boost::shared_ptr<Derived> &alias1 = pDerived;  // works fine 
    const boost::shared_ptr<Base> &alias2 = pDerived; // also works fine 
    boost::shared_ptr<Base> &alias3 = pDerived;   // compilation error 

    //native pointers 
    Derived *alias4 = pDerived.get();  //works 
    const Base *alias5 = pDerived.get(); //works 
    Base *alias6 = pDerived.get();  //works 

    //native references 
    Derived &alias7 = *pDerived;   // works 
    const Base &alias8 = *pDerived;  // works 
    Base &alias9 = *pDerived;    // works 
} 

Я не понимаю, почему назначение alias2 это прекрасно, но присваивание alias3 дает ошибку компилятора. Может ли кто-нибудь объяснить это? Мне нужна функциональность, как пример alias3, и я не могу заставить ее работать.

+0

'станд :: shared_ptr & alias3 = static_cast <станд :: shared_ptr > (pDerived);' – user2296177

+0

Вы также можете попробовать использовать подталкивания 'static_cast':' alias3 = повышение :: static_pointer_cast (pDerived); ' – pingul

+0

Как и в случае с Эйссой Н., приведение результатов приводит к ошибке компиляции: 'недопустимая инициализация неконстантной ссылки типа âboost :: shared_ptr & â из rvalue типа âboost :: shared_ptr â boost :: shared_ptr & alias3 = boost :: static_pointer_cast (pDerived); 'Даже если это сработало, создание временного объекта rval - именно то, чего я пытаюсь избежать по соображениям эффективности. – njensen

ответ

0

Эта проблема не связана с повышающими или умными указателями. Это может случиться с типами POD тоже, как показано на следующем простом примере:

int main() { 
    int x = 0; 
    const double &y = x; //fine 
    double &z = x; //error! 
    return 0; 
} 

Причина заключается в том, что временное значение (Rvalue) может связываться с const&, но он не может связываться с &. Что происходит в double &z = x, так это то, что x и z являются несвязанными типами, а x необходимо преобразовать в double и создать временную переменную, которая не может связываться с &.

+0

Eissa N. - Я подозреваю, что вы абсолютно правы; Спасибо. Однако см. Дополнительные строки, добавленные в пример. Родные указатели и ссылки, похоже, не требуют создания временного rval, как вы предлагаете (возможно, потому, что компилятор изначально понимает смещения членов в конкатенированных структурах). Возможно, это еще один способ, которым контейнеры/шаблоны shared_ptr не являются чистыми заменами для своих родных коллег. – njensen

+0

@njensen Если вы сравниваете исходные указатели со смарт-указателями, вы должны проверить 'Derived * pDerived = new Derived; Base * & alias = pDerived; 'который снова терпит неудачу. –

+0

Я бы проголосовал за вас, если бы мог; по-видимому, я слишком новичок в подсчете голосов. Я согласен, что ваш последний пример точно раскрывает проблему. – njensen

Смежные вопросы