0

假设我有以下代码。我原以为这至少要给我一个警告。

#include <iostream>

struct test
{
    int whatever;
};

int main()
{
    int test::* p = &test::whatever;    
    std::cout << p;
}

然而,我惊讶地发现这段代码编译时没有任何抱怨。所以我想知道,这种情况下实际打印的是什么,是怎么test::whatever存储的,所以我们可以访问它的地址?

4

3 回答 3

3

test::whatever 存储如何

这在语言中没有指定。但是我们可以做出合理的猜测,它存储了从对象开头到指向成员的偏移量。

所以我们可以访问它的地址?

不。

在这种情况下实际打印的内容

1 被打印出来。

成员指针没有运算符重载。但是 bool 有一个重载,并且成员指针可以转换为 bool。当它们不为空时,它们将转换为 true。p不为空,因此它转换为打印为 1 的 true。

于 2021-08-31T11:22:53.767 回答
1

这里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++ 中的指针成员 ->* 和 .* 运算符。

于 2021-08-31T11:21:29.760 回答
0

它是成员指针,正如第一个答案中已经指出的那样。您可以使用它来指向不同对象的不同成员:


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;
}
于 2021-08-31T11:23:56.543 回答