Самый переносимый и надежный способ получить адрес переменной в C++
С помощью &
получить адрес переменной может быть проблематично, если тип переменной перегружен operator&()
, Например, _com_ptr_ имеет operator&()
перегружен с побочным эффектом изменения объекта.
Теперь у меня есть сложный набор шаблонов с такими функциями:
template<class T>
void process( const T* object )
{
//whatever
}
template<class T>
void tryProcess( T& object )
{
process( &object )
}
В tryProcess()
Мне нужно получить T*
указатель, содержащий адрес фактического объекта типа T
,
Вышеуказанная реализация tryProcess()
будет работать нормально только если class T
не имеет operator&()
перегружен. Так что если я позвоню tryProcess<_com_ptr_<Interface>>()
Я могу получить неожиданные результаты - перегружен operator&()
срабатывает.
В другом вопросе предлагается следующий обходной путь:
template<class T>
T* getAddress( T& object )
{
return reinterpret_cast<T*>( &reinterpret_cast<char&>( object ) );
}
С такой функцией я могу реализовать tryProcess()
следующее:
template<class T>
void tryProcess( T& object )
{
process( getAddress( object ) )
}
и всегда будет иметь одинаковое поведение независимо от того, class T
имеет operator&()
перегружен. Это обеспечивает нулевые накладные расходы при оптимизации в Visual C++ 7 - компилятор получает то, что нужно сделать, и просто получает адрес объекта.
Насколько портативным и стандартно-совместимым является это решение проблемы? Как это можно улучшить?
2 ответа
Это стандартная жалоба. Вопрос был доведен до сведения комитета ISO C++ в связи с проблемами с offsetof
реализации, которые сломались на этом. Среди рассмотренных решений было ужесточение определения POD или добавление дополнительного ограничения на типы, которые будут использоваться с offsetof
, Эти решения были отклонены, когда reinterpret_cast
Решение было вынесено. Поскольку это предлагало совместимое со стандартами решение проблемы, комитет не видел необходимости добавлять дополнительные требования к offsetof
и оставил исправления для реализаций.
Увеличениеaddressof
реализуется с этим reinterpret_cast
трюк, так что я бы сказал, что он, вероятно, портативный и соответствует стандартам.
Здесь вы можете увидеть рассматриваемый код.