问题
Check following code:
#include <iostream>
using namespace std;
int& foo() {
static int i = 0;
return i;
}
int main() {
cout << &foo() << endl;
cout << &foo << endl;
return 0;
}
As you see, the first cout
prints address of return value of foo()
which will be static variable i
inside foo()
. For 2nd cout
I was expecting that &foo
returns address of foo()
function, as stated here:
2) If the operand is a qualified name of a non-static member, e.g. &C::member, the result is a prvalue pointer to member function or pointer to data member of type T in class C. Note that neither &member nor C::member nor even &(C::member) may be used to initialize a pointer to member.
But to my surprise, this is my output:
0x5650dc8dc174
1
First one is ok, but 2nd one is 1
? How this happened? To make sure that I have not messed up anything, I wrote this code in C
:
#include <stdio.h>
int foo() {
}
int main(void) {
printf("%p", &foo);
return 0;
}
with following output:
0x55732bd426f0
which works as expected. Have I missed up something in C++
code? or maybe this is because of inlining foo
function (even though it should not be like this)?
回答1:
std::basic_ostream::operator<< has two overloads taking bool
and const void*
; note there's no overload taking function pointer.
basic_ostream& operator<<( bool value ); (6) basic_ostream& operator<<( const void* value ); (7)
For both int*
and function pointer passed to std::basic_ostream::operator<<
, implicit conversions are required here.
When passing int*
, the (7) overload is selected because the implicit conversion converting from int* to const void* is perferred than the one converting to bool
in overload resolution,
If two conversion sequences are indistinguishable because they have the same rank, the following additional rules apply:
1) Conversion that involves pointer to bool, pointer-to-member to bool, or std::nullptr_t to bool conversion is worse than the one that doesn't
and
A prvalue pointer to any (optionally cv-qualified) object type T can be converted to a prvalue pointer to (identically cv-qualified) void. The resulting pointer represents the same location in memory as the original pointer value.
When passing function pointer, the (6) overload is selected; function pointer can be converted to bool implicitly, but not to const void*
.
A prvalue of integral, floating-point, unscoped enumeration, pointer, and pointer-to-member types can be converted to a prvalue of type bool.
The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become false. All other values become true.
回答2:
There is no overload for operator<<
that matches the function pointer. So best match is basic_ostream& operator<<(bool value)
.
There is another overload of operator<<
as basic_ostream& operator<<(const void * value)
. But function pointers could not implicitly cast to const void*
.
If you would like to print the address of a function you could cast it to void *
by using reinterpret_cast
or C style casts.
回答3:
What you see is that the
std::ostream& operator<<( bool );
From cppreference:
There are no overload for pointers to non-static member, pointers to volatile, or function pointers (other than the ones with signatures accepted by the (10-12) overloads). Attempting to output such objects invokes implicit conversion to bool, and, for any non-null pointer value, the value 1 is printed (unless boolalpha was set, in which case true is printed).
To see the pointer value you can cast to void*
:
std::cout << (void*)foo;
来源:https://stackoverflow.com/questions/53129402/why-pointer-to-function-is-equal-to-1