假设我有以下代码。我原以为这至少要给我一个警告。
#include <iostream>
struct test
{
int whatever;
};
int main()
{
int test::* p = &test::whatever;
std::cout << p;
}
然而,我惊讶地发现这段代码编译时没有任何抱怨。所以我想知道,这种情况下实际打印的是什么,是怎么test::whatever
存储的,所以我们可以访问它的地址?
假设我有以下代码。我原以为这至少要给我一个警告。
#include <iostream>
struct test
{
int whatever;
};
int main()
{
int test::* p = &test::whatever;
std::cout << p;
}
然而,我惊讶地发现这段代码编译时没有任何抱怨。所以我想知道,这种情况下实际打印的是什么,是怎么test::whatever
存储的,所以我们可以访问它的地址?
test::whatever 存储如何
这在语言中没有指定。但是我们可以做出合理的猜测,它存储了从对象开头到指向成员的偏移量。
所以我们可以访问它的地址?
不。
在这种情况下实际打印的内容
1 被打印出来。
成员指针没有运算符重载。但是 bool 有一个重载,并且成员指针可以转换为 bool。当它们不为空时,它们将转换为 true。p
不为空,因此它转换为打印为 1 的 true。
这里p是指向成员的指针。它就像类成员相对于对象基地址的偏移量。它本身并不指向内存中的任何地方。它需要一个基础对象指针来指向某个地方。因此,在没有对象的情况下拥有指向成员的指针并不是非法的,恰恰相反:它是这种类型的用例。
你可以像这样使用它:
#include <iostream>
struct test
{
int whatever;
};
int main()
{
int test::* p = &test::whatever;
test t = {5};
std::cout << t.*p << std::endl; // prints 5
}
但是,我不知道您给出的示例中打印的是什么。
请参阅 C++ 中的指针成员 ->* 和 .* 运算符。
它是成员指针,正如第一个答案中已经指出的那样。您可以使用它来指向不同对象的不同成员:
struct test
{
int whatever;
};
int main()
{
int test::* p = &test::whatever;
test w1{ 123 }, w2{ 234 };
std::cout << p<< endl; //point to member
std::cout << w1.*p << endl; //value of first whatever
std::cout << w2.*p << endl; //value of second whatever
//real address of whatever of w1 and w2, compare
std::cout << &(w1.*p) << "=="<< &w1.whatever<< endl;
std::cout << &(w2.*p) << "=="<< &w2.whatever<< endl;
std::cout << p << endl; //yet pointer did not change
return 0;
}