Когда использовать addressof (x) вместо & x?
Как мне решить, нужен ли мне addressof(x)
вместо &x
при принятии адреса объекта?
Похоже, вопрос был путаным, поэтому уточнение в порядке:
addressof
, очевидно, обходит перегруженный адрес оператора. Я уже знаю об этом.
Что я хочу знать:
Как узнать, что я действительно хочу сделать? (Особенно, если внутри шаблона и т.д.)
Есть ли какое-то "правило", которое помогает мне разобраться, когда мне нужно addressof
вместо &
?
В конце концов, они оба возвращают "адрес" объекта, поэтому, когда я использую который?
Ответы
Ответ 1
Вы используете std::addressof
, когда вам нужно. К сожалению, "когда вам нужно" включать в любое время, когда вы работаете в коде шаблона, и хотите превратить переменную неизвестного типа T
или T&
в указатель с честной привязкой к этой переменной памяти.
Поскольку комитет С++ по глупости допускал перегрузку ссылочного оператора (до небольшой законной цели), пользователь может создать экземпляр вашего шаблона с каким-то типом, который вы не можете использовать ссылочным оператором для получения фактического указателя на, std::addressof
- это способ обойти пользователей, которые используют эту сомнительную функцию С++, чтобы сделать то, что должен гарантировать гарантированный язык для начала.
Короче говоря, это исправление библиотеки для глупости языка. Используйте его в коде шаблона вместо &
, если вы хотите убедиться, что пользователи не могут сломать ваш код. Если вашим пользователям можно доверять не использовать эту иль-задуманную функцию, вы можете использовать &
.
Ответ 2
Если это пользовательский тип с перегруженным унарным operator&
, и вы хотите его адрес, используйте addressof
.
Я бы сказал, что вы всегда должны использовать &
, потому что, как вы говорите, если вы этого не сделаете, он побеждает цель перегрузки. Если, конечно, вы не делаете что-то значимое с перегрузкой, в этом случае вам понадобится addressof
(вне класса, внутри вы можете просто использовать this
), но вы должны быть очень уверены в том, что делаете.
Здесь больше - если вы хотите перегрузить operator&
вне класса (вы можете), вы должны использовать addressof
для возврата адреса, в противном случае это приведет к бесконечной рекурсии:
struct Class
{
virtual ~Class() {}
int x;
};
void* operator&(const Class& x)
{
//return &x; <---- infinite recursion
return addressof(x) + 4; //I know this isn't safe
//but I also know the intrinsics of my compiler
//and platform to know this will actually return
//the address to the first data member
}
Я знаю, что это не безопасно.
Ответ 3
Только мое мнение:
Если вы не являетесь частью команды, разрабатывающей класс и его интерфейс, никогда. Я лично никогда не видел веских причин перегружать этого оператора. Но если кто-то разрабатывает класс, где это имеет смысл, и предполагается, что класс предназначен для общественного потребления (т.е. Класс не предназначен для внутреннего использования только в конкретной библиотеке), я ожидаю, что класс будет работать в обычном коде что, естественно, ожидает, что &
означает "адрес". Если класс, который перегружает оператор, не разработан таким разумным способом, я бы не использовал этот класс, период. Потому что либо этот класс сломан, либо он не предназначен для использования вне библиотеки, частью которой является.
Ответ 4
Используйте его, когда вы хотите узнать фактический адрес объекта, а не результат перегрузки адреса operator&
.
Ответ 5
В конце концов, оба они возвращают "адрес" объекта, поэтому, когда я использую какой?
У вас нет абсолютно никакой гарантии, что перегруженный operator&
является "адресом" объекта, скорее всего, это не так, или автор класса, вероятно, не стал бы его перегружать. Они могли бы перегрузить его, чтобы вернуть другой тип, или даже вернуть void
, если они недоброжелательно пытаются помешать людям принимать свой адрес.
Если вы хотите, чтобы указатель на объект, который мог перегружать &
(например, потому что его тип является параметром шаблона, поэтому вы не знаете), либо используйте std::addressof
, либо документ, чтобы ваш шаблон не поддерживал типы которые не возвращают реальный адрес объекта как правильный тип.