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

Ant*_*ois 11 c++ pointer-to-member language-lawyer

我有以下代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

它的输出是:

field: 1 - a                                                                                                                                                                                                              
field: 1 - b                                                                                                                                                                                                              
field: 1 - c  
Run Code Online (Sandbox Code Playgroud)

我在理解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);
Run Code Online (Sandbox Code Playgroud)

但这似乎是因为field呼叫的价值不变.我错过了什么?该标准描述的具体操作究竟如何?

Mik*_*our 18

<<格式化成员指针的值没有重载,所以如果你尝试,你将不会得到任何特别有用的东西.有一个重载bool,成员指针可以转换为bool,这就是这里发生的事情.指针不为null,因此它将转换为true,默认情况下格式为1.

为了进一步演示,您可以先尝试流媒体boolalpha; 然后你应该看到true而不是1.

  • @martin:如果你试图打印一个成员指针,这将给出未定义的行为.C++ I/O至少是类型安全的,如果有时令人困惑的话. (5认同)
  • 哇,这教会我留下好旧的printf,如果只是因为我理解它更好. (2认同)

Tar*_*ama 7

  1. field正如您所说,类型是指向foo_s类型成员的指针std::string.

  2. 的值field1在所有这些情况下,因为指向成员可以转化为bool,所以当你输出它们,你就会得到一个1,因为它们不为空.