指向C ++中成员的指针如何在内部工作?

Jee*_*eja 1 c++ pointers datamember

我想知道指向成员的指针如何在C ++中工作。

我查看了一些地方,发现它们存储了某种偏移量。并使用以下事实:成员在内存中的出现顺序与它们在类/结构定义中声明的顺序相同。但是...

#include <iostream>
#include<typeinfo>
using namespace std;
struct S
{
    S(int n): mi(n) {}
    int mi;
    int k;
    int f()  {return mi+k;}
};

int main()
{
    S s(7);
    int S::*pmi = &S::mi;
    int S::*lop = &S::k;
    int (S::*sf)() = &S::f;
    cout<<&S::mi<<endl<<&S::k<<endl<<&S::f<<endl<<pmi<<endl<<lop<<endl<<sf<<endl;
    cout<<typeid(lop).name()<<endl;
}
Run Code Online (Sandbox Code Playgroud)

我希望看到一些补偿。但是,第一行中cout <<的所有值都给出1作为输出。

我不明白,如果所有人都给1,关于偏移量的信息存储在哪里?

如果您可以解释实际情况,那将非常有帮助。

eer*_*ika 7

Iostream插入运算符没有指向成员的指针的重载。

但是,有一个重载bool,并且指向成员的指针可以隐式转换为bool-指向成员的空指针将转换为false,否则为true。bool如果为true,则流为1;如果为false,流为0。因此,您正在观察的输出是以下事实:指向成员的指针都不为空。

我尝试通过++ ..递增,但这也行不通..

增量不起作用,因为指向成员的指针不支持指针算术。

那么,有什么方法可以实际看到偏移值?

可以将任何内容视为字节数组,因此您可以使用一些辅助函数来惊叹成员指针的内容:

template<class T>
void print_raw(const T& obj) {
    const unsigned char* cptr = reinterpret_cast<const unsigned char*>(&obj);
    const unsigned char* end = cptr + sizeof(T);
    while(cptr < end) {
        printf("%02hhx ", *cptr++); // is there simple way with iostreams?
    }
    std::cout << '\n';
}

std::cout << "pmi: ";
print_raw(pmi);
std::cout << "lop: ";
print_raw(lop);
std::cout << "sf:  ";
print_raw(sf);
Run Code Online (Sandbox Code Playgroud)

我的系统上的示例输出:

pmi: 00 00 00 00 00 00 00 00 
lop: 04 00 00 00 00 00 00 00 
sf:  f0 08 40 00 00 00 00 00 00 00 00 00 00 00 00 00 
Run Code Online (Sandbox Code Playgroud)

这可能使您对编译器如何实现它们有一些了解。注意,如果实现包括任何填充字节/位,则这些填充字节/位可以具有任何值,因此任何非零值都可能没有意义。

成员对象指针的输出看起来非常明显。看起来像是到对象的64位小端偏移量。mi在偏移量0处,k偏移量为4个字节。