通过引用传递函数 - 如何获取地址?

jos*_*ike 0 c++

C++ 新手,学习是为了乐趣。我仍在尝试理解引用和取消引用语法,所以如果您正在阅读本文,请用心并请帮助解释(如果可以的话)。一般来说,我理解=& foo返回对象的引用foo。并且引用 by&foo应该能够像指针一样显示它所引用的对象的地址。所以这可以赎回 foo 的地址:

//EXAMPLE 1 - works as expected?
void useFooRef(int &foo) {    
    cout << "using foo @ " << &foo << endl; //using foo @ 0x16eebb4e8
    //no warning here!
}

int foo = 1;

int main() {
    useFooRef(foo);
    return (0);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果foo是我传递的函数,则将其作为指针接收并提取其地址似乎很好;尽管如此,我读到通过引用传递以避免传递空指针更安全。但如果我这样做,我会收到编译器警告......

//EXAMPLE 2
void useFooPtr(int (*foo)()) {
    cout << "using foo @ " << &foo << endl; //using foo @ 0x16fb634c8
    //no warning here!
};

void useFooRef(int (&foo)()) {
    cout << "using foo @ " << &foo << endl; //using foo @ 1
    //warning: reference cannot be bound to dereferenced null pointer in well-defined C++ code
};

int foo() {
    return (3);
};

int main() {
    useFooPtr(foo);
    useFooRef(foo);
    return (0);
}
Run Code Online (Sandbox Code Playgroud)

我试图理解正在传递的内容,例如:我现在对 C++ 的心理图是变量名包含一些关于其自己的内存槽的元数据,而引用包含它的内存槽指的是,并且指针包含其自己的内存槽,该内存槽保存它所指向的事物的槽。在传递函数的情况下,当函数接收引用与指针时,此元数据会是什么样子,以及为什么可以使用示例&foo1 中作为引用传递的简单 int 来提取内存地址,但当它是示例 2 中作为引用传递的函数时则不然……即使如果它作为指针接收,则在这两种情况下都foo 可以提取地址?

S.M*_*.M. 6

std::cout::operator<<没有 的重载版本int (*foo)(),因此它使用std::cout::operator<<(bool)并输出

std::cout << static_cast<bool>(&foo)  // 0 or 1.
Run Code Online (Sandbox Code Playgroud)

警告:在定义良好的 C++ 代码中,引用无法绑定到取消引用的空指针

这不是完整的警告文本。老实说,阅读不完整的警告是一个导致学习失败的坏习惯。完整的警告文本非常清楚:

警告:在定义良好的 C++ 代码中,引用不能绑定到取消引用的空指针;可以假定指针始终转换为 true [-Wundefine-bool-conversion]

众所周知,引用是现有对象的别名,其地址可能不是nullptr。编译器警告您它将始终输出1. GCC还提出了明确的警告:

警告:编译器可以假设“foo”的地址永远不会为 NULL [-Waddress]

void useFooPtr(int (*foo)()) {
    cout << "using foo @ " << &foo << endl; //using foo @ 0x16fb634c8
    //no warning here!
};
Run Code Online (Sandbox Code Playgroud)

foo @ 0x16fb634c8- 这里输出局部变量的地址foo。函数地址由 输出std::cout << foo,它也会输出foo @ 1

如果要输出函数的地址,请将其转换为void*

std::cout << reinterpret_cast<void*>(foo)
Run Code Online (Sandbox Code Playgroud)