Почему *

#c #pointers #reference

#c #указатели #ссылка

Вопрос:

Краткая версия:

Следующий код не компилируется:

 CComBSTR temp;
CMenu().GetMenuString(0,   temp, 0);
  

но это делает:

 CComBSTR temp;
CMenu().GetMenuString(0, *amp;temp, 0);
  

Почему?


Полный код:

 #include <atlbase.h>
extern CComModule _Module;
#include <atlapp.h>
#include <atlwin.h>
#include <atlctrls.h>

int main() {
    CComBSTR temp;
    CMenu().GetMenuString(0, *amp;temp, 0);
}
  

GetMenuString подпись (из atluser.h , из WTL):

 BOOL GetMenuString(UINT nIDItem, BSTRamp; bstrText, UINT nFlags) const;
  

Комментарии:

1. Что это, я даже не знаю? Какова подпись для GetMenuString

2. @JesusRamos: Извините, я забыл включить это. Это часть WTL; Я добавил его внизу.

Ответ №1:

Потому что унарные операторы amp; и * могут быть перегружены, что, я думаю CComBSTR , и происходит.

* Обновить: *

Для тех, кто задается вопросом, как получить адрес переменной, тип которой перегружен operatoramp; , есть TR1 std::addressof и его улучшенная реализация для совместимости с C 03.

Комментарии:

1. @kprobst: Подождите, amp; может быть перегружен?? черт возьми!! Как тогда получить адрес переменной ?!

2. @Mehrdad: с реализацией TR1 std::addressof или Boost для совместимости с C 03.

3. @Mehrdad: вы могли бы привести его к другому типу указателя. Но я согласен, что перегруженный оператор amp; — это минное поле путаницы

4. Вы могли бы сделать что-то вроде этого (на самом деле не проверяли код): template < имя_типа T > T * address_of (T amp; t) { return ( reinterpret_cast<T*>( amp; const_cast<charamp;( reinterpret_cast<const volatile char amp;>( t ) ) ) ); }

5. @Mehrdad : Посмотрите на open-std.org/jtc1/sc22/wg21/docs/papers/2001/n1324.html в разделе «Получение адреса объекта с помощью перегруженного оператораamp;». Это довольно надуманно, но, с другой стороны, объект интеллектуального указателя не должен использоваться через его собственный адрес, только через адрес, который он содержит. Это похоже на получение адреса переменной указателя вместо ее значения (которое является адресом указанных данных), поэтому случаи, когда вы хотите получить реальный адрес интеллектуального указателя, действительно ограничены

Ответ №2:

CComBSTR возможно, было перегружено operator * или operator amp; для возврата типа, который соответствует типу параметра, полученного GetMenuString()

Таким образом, хотя *amp;x это то же x самое, что и для встроенных типов данных, это может быть не то же самое для пользовательских типов.

Ответ №3:

operatoramp; on CComBSTR перегружен и возвращает a BSTR* , поэтому разыменование дает вам нужный вам тип, то есть a BSTR .

Ответ №4:

Если он не компилируется, то у вас должно появиться значимое сообщение об ошибке?

Функция определяется следующим образом и требует BSTRamp; :

 BOOL GetMenuString(UINT nIDItem, BSTRamp; bstrText, UINT nFlags) const
  

CComBSTR класс не приводит к BSTRamp; себе, но через amp; operator * operator , за которым он следует.