为什么对于同一结构体的不同成员,指向成员的指针的值总是相同的?

Why is the value of a pointer-to-member always the same for different members of the same struct?

本文关键字:成员 指针 于同一 结构体 为什么      更新时间:2023-10-16

我有以下代码:

#include <iostream>
#include <string>
using namespace std;
struct foo_s {
    string a;
    string b;
    string c;
};
void print_field(foo_s* foo, string foo_s::* field) {
    cout << "field: " << field << " - " << foo->*field << endl;
}
int main() {
   foo_s my_foo = {
       "a",
       "b",
       "c",
   };
   print_field(&my_foo, &foo_s::a);
   print_field(&my_foo, &foo_s::b);
   print_field(&my_foo, &foo_s::c);
   return 0;
}

输出为:

field: 1 - a                                                                                                                                                                                                              
field: 1 - b                                                                                                                                                                                                              
field: 1 - c  

我在理解print_field()函数中发生的事情的细节方面有点困难。即:

  1. field是什么类型的?我猜是pointer-to-string-foo_s-member
  2. 为什么field的值总是相同的(在这种情况下是1),而foo->*field产生不同的结果?

主要是我对第2点感到困惑。我想象字段将是结构体开始的"偏移量",foo->*field将在概念上等同于

之类的内容。
char* ptr = static_cast<char*>(foo);
ptrdiff_t offset = somehow_get_the_byte_offset_from_pointer_to_member(field);
ptr = ptr[offset];
string result = *static_cast<string*>(ptr);

,但这似乎是出来的,因为field的值在调用中没有变化。我错过了什么?这个具体的操作是如何被标准描述的?

<<没有重载来格式化成员指针的值,所以如果您尝试的话,不会得到任何特别有用的东西。bool有一个重载,成员指针可以转换为bool,这就是这里发生的事情。该指针不是空的,所以它转换为true,默认格式为1

为了进一步演示,您可以先尝试流式传输boolalpha;那么你应该看到true而不是1

  1. 如您所说,field的类型是指向foo_sstd::string类型成员的指针。

  2. 在所有这些情况下,field的值都是1,因为指向成员的指针可以转换为bool,所以当你输出它们时,你得到的是1,因为它们不是空的。