英文:
How the function of the class itself has a different address from its objects' functions' addresses?
问题
我知道在类中,每个对象的变量在内存中都有不同的地址。但是,成员函数的地址在对象之间是共享的,因此只有一个函数以共同的地址加载到内存中。
问题是,我试图打印类本身某个成员函数的地址,我期望它与所有对象的成员函数地址相同。但我发现它与它们不同!对我来说这很奇怪。
#include<iostream>
using namespace std;
class LuckyNum {
public:
void PrintAddress() {
printf("\tFunction address: %p\n", &LuckyNum::PrintAddress);
}
};
int main() {
LuckyNum r1;
cout << "r1:\n";
r1.PrintAddress();
LuckyNum r2;
cout << "r2:\n";
r2.PrintAddress();
cout << "LuckyNum Class:\n";
printf("\tFunction address: %p\n", &LuckyNum::PrintAddress);
return 0;
}
/*输出结果!! :
r1:
Function address :0000007acdbffda0
r2:
Function address :0000007acdbffda0
LuckyNum Class:
Function address :0000007acdbffde0 => 为什么会这样!!它应该与上面两个地址相等,不是吗?
<details>
<summary>英文:</summary>
I know in classes that each object's variables will have a different address in memory. However, member functions' addresses are common between objects, so only one function is loaded in memory with a common address.
The issue is I was trying to print the address of a certain member function of the class itself and I expected it to be the same as the member function's address of all objects. But I found that it's different from them!! That was very strange for me.
#include<iostream>
using namespace std;
class LuckyNum {
public:
void PrintAddress() {
printf("\tFunction address :%p\n", &LuckyNum::PrintAddress);
}
};
int main() {
LuckyNum r1;
cout << "r1:\n";
r1.PrintAddress();
LuckyNum r2;
cout << "r2:\n";
r2.PrintAddress();
cout << "LuckyNum Class:\n";
printf("\tFunction address :%p\n", &LuckyNum::PrintAddress);
return 0;
}
/*Output!! :
r1:
Function address :0000007acdbffda0
r2:
Function address :0000007acdbffda0
LuckyNum Class:
Function address :0000007acdbffde0 => HOW!! it should equal the above two addresses, shouldn't it?
*/
</details>
# 答案1
**得分**: 3
```plaintext
printf("\tFunction address :%p\n", &LuckyNum::PrintAddress);
printf("\tFunction address :%p\n", &LuckyNum::PrintAddress); 会引发未定义行为。 `printf` 不是类型安全的,`&LuckyNum::PrintAddress` 不是一个指针。它是一个_成员指针_,这是一种非常不同的东西,其表示是实现定义的。请参见以下程序:
#include
#include
#include
class LuckyNum {
public:
std::vector
auto const address = &LuckyNum::getAddress;
std::vector
std::memcpy(result.data(), &address, sizeof(address));
return result;
}
};
int main() {
LuckyNum r;
auto address = r.getAddress();
auto const address2 = &LuckyNum::getAddress;
if (address.size() != sizeof(address2)) {
std::cout << "Fail\n";
return -1;
}
int result = std::memcmp(address.data(), &address2, address.size());
if (result != 0) {
std::cout << "Fail\n";
return -1;
}
std::cout << "Success\n";
return 0;
}
`getAddress()` 函数将成员指针 `&LuckyNum::getAddress` 存储在字节向量中并返回它。然后,`main` 通过 `getAddress()` 函数获取一个成员指针,然后直接通过 `&LuckyNum::getAddress` 获取另一个成员指针。然后,它逐字节比较 [如果运行程序](https://godbolt.org/z/qfT83jxEj)(至少使用 gcc),您会发现这两个成员指针确实相等。
英文:
The function call
printf("\tFunction address :%p\n", &LuckyNum::PrintAddress);
invokes undefined behaviour. printf
is not typesafe, and &LuckyNum::PrintAddress
is not a pointer. It is a pointer to member, which is a very different thing and it's representation is implementation defined.
See the following program:
#include <iostream>
#include <vector>
#include <cstring>
class LuckyNum {
public:
std::vector<char> getAddress() {
auto const address = &LuckyNum::getAddress;
std::vector<char> result(sizeof(address));
std::memcpy(result.data(), &address, sizeof(address));
return result;
}
};
int main() {
LuckyNum r;
auto address = r.getAddress();
auto const address2 = &LuckyNum::getAddress;
if (address.size() != sizeof(address2)) {
std::cout << "Fail\n";
return -1;
}
int result = std::memcmp(address.data(), &address2, address.size());
if (result != 0) {
std::cout << "Fail\n";
return -1;
}
std::cout << "Success\n";
return 0;
}
The getAddress()
function stores the pointer to member &LuckyNum::getAddress
in a vector of bytes and returns it. main
then obtains one pointer to member via the getAddress()
function and another one directly via &LuckyNum::getAddress
. Then it compares to the byte by byte and if you run the program (with gcc at least) you will find that the two pointers to member are indeed equal.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论