2016-10-31 16 views
0

У вас есть два класса Animal и Dog (где Dog унаследовано от Animal), и у Вас есть ситуация, где вы часто ожидающие животное, но отправляете экземпляр собаки. В моем конкретном случае я часто бросаю сильный указатель (std::shared_ptr<Dog>) на ожидаемую звездой функцию (std::shared_ptr<Animal>).C++ reinterpret_cast ссылки станда :: shared_ptr для оптимизации

Если мы согласны с тем, что мы можем сделать параметр функции ссылкой (std::shared_ptr<Animal>&, избегая аргументов о том, почему у вас не должно быть сильных указателей в качестве ссылочных параметров из-за проблем с изменением прав собственности на потоки), я полагаю, что мы будем в безопасности -поля для литья std::shared_ptr<Dog> dog с использованием reinterpret_cast<std::shared_ptr<Animal>&>(dog), правильно?

И если да, то что может возникнуть, кроме проблем с резьбой; как, например, эталонный счетный сорт?

Чтобы быть ясным, цель состоит в том, чтобы иметь решение, которое будет использоваться во многих случаях, когда литье однажды не является жизнеспособным решением. Это больше проблема, что есть много объектов, которые нужно было бы отличить. Кроме того, игнорирование того, что std::unique_ptr может быть или не быть лучшим решением.

Чтобы добавить окончательное требование - использование простых указателей не позволило бы мне изменить оригинал std::shared_ptr в случае универсальной функции класса сериализатора, которая является виртуальной и, следовательно, не может быть сделана шаблоном.

+0

Почему бы вам не использовать ['static_pointer_cast'] (http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast)? – krzaq

+0

Чтобы избежать накладных расходов. В моем конкретном случае это то, где генерируется код. Или в случае создания пользовательского конструктора копирования, где у вас есть несколько уровней наследования, и вам нужно продолжать кастинг вверх. –

+0

Связаны ли эти классы по наследству? – Steve

ответ

0

Я часто бросает сильный указатель (std::shared_ptr<Dog>) на функцию животных ожидая (std::shared_ptr<Animal>).

Там нет необходимости подавать (т.е. явно новообращенных). Общий указатель на производный тип неявно конвертируется (1) в общий указатель на базовый класс.

(а) Если мы признаем, что мы можем сделать параметр функции ссылку

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

Также считайте, что если ссылка не является константой, то вы не можете полагаться на неявное преобразование (1). Вместо этого вы должны создать отдельный общий указатель правильного типа (вы можете использовать неявное преобразование для его создания и передать его. Аргумент ссылки на константу или аргумент без ссылки не имеет этой проблемы.

(b) Я предполагаю, что мы были бы в безопасности памяти мудрой, чтобы бросить станд :: shared_ptr собаку, используя reinterpret_cast<std::shared_ptr<Animal>&>(dog), право

Стандарта-мудрый, ваш Рекомендованный бросок не является безопасным -. она имеет неопределенное поведение я не вижу как предположение (б) следует из предположения (а).


Если это прекрасно, чтобы использовать ссылку на shared_ptr в качестве аргумента в вашем случае, но вы не можете избежать увеличения/уменьшения в refcounter за счет преобразования (производный на базу, неконстантного на константные), я рекомендую использовать вместо этого указатель горит указателем.

+0

Возможно, ваше предложение просто использовать обычный указатель может обрабатывать собственный экземпляр конструктора копии, который у меня есть. Однако одно предостережение использовать пустой указатель состоит в том, что я не могу изменить исходный 'std :: shared_ptr' сам, в тех случаях, когда я действительно действительно хочу это сделать. Например, у меня есть обобщенный метод 'Serialize()', который должен изменить переменную, и сам метод не может быть шаблонным, потому что он должен быть виртуальным. –

+0

Возможно, вы можете передать пустой указатель и вернуть пустой указатель, который затем присваиваете 'shared_ptr' (после down casting, поскольку функция, которая не может принять общий указатель производного типа, не может возвращать производный указатель). – user2079303