为什么打印结构的数据成员的地址启用,尽管没有对象?

Why does printing address of data member of a struct enabled, although there is no object?

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

#include <iostream>

struct test
{
    int whatever;
};

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

但是,我惊讶地发现这段代码可以毫无怨言地编译。所以我想知道,在这种情况下实际打印的是什么,test::whatever 是如何存储的,所以我们可以访问它的地址?

这里p是指向成员的指针。它就像 class 成员相对于对象基地址的偏移量。它本身并不指向内存中的任何地方。它需要一个基础对象指针指向某处。因此没有对象的成员指针并不违法,恰恰相反:它是这种类型的用例。

您可以像这样使用它:

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

how is the test::whatever stored

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

so we can access its address?

没有

what is actually printed in this case

1 已打印。

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

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


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;
}