指向数据成员的指针的单个声明为该类的每个对象创建指针。
不,它会创建一个指向成员的指针(尽管可以作为从对象基础的偏移量)
然后您可以将它与指向对象的指针一起使用以获取该成员。
struct S
{
int x;
int y;
};
int S::* ptrToMember = &S::x; // Pointer to a member.
S obj;
int* ptrToData = &obj.x; // Pointer to object
// that happens to be a member
请注意,在创建指向成员的指针时,我们不使用对象(我们只使用类型信息)。所以这个指针是类中的一个偏移量,用来获取一个特定的成员。
您可以通过指针或对象访问数据成员。
(obj.*ptrToMember) = 5; // Assign via pointer to member (requires an object)
*ptrToData = 6; // Assign via pointer already points at object.
为什么会发生这种情况,而不是创建一个指向类的一个特定实例的指针?
这称为指针。
一个类似但平行的概念(见上文)。
支持这个想法的逻辑是什么?
愚蠢的例子:
void addOneToMember(S& obj, int S::* member) { (obj.*member) += 1; }
void addOneToX(S& obj) { addOneToMember(obj, &Obj::x);}
void addOneToY(S& obj) { addOneToMember(obj, &Obj::y);}
另外,如果我正确理解这一点,这将意味着在指针初始化时分配的内存量是无限的/可变的,因为当时可能存在任意数量的对象。
不,因为指向成员的指针只是对象的偏移量。您仍然需要实际对象来获取值。
最后,如何为这些指针分配内存?
与其他对象相同。就布局而言,它们没有什么特别之处。
但实际布局是实现定义的。因此,如果不参考编译器,就无法回答这个问题。但这对你来说真的没有用。
是否可以看到这些指针的物理内存地址?
当然。它们就像其他物体一样。
// Not that this will provide anything meaningful.
std::cout.write(reinterpret_cast<char*>(&ptrToMember), sizeof(ptrToMember));
// 1) take the address of the pointer to member.
// 2) cast to char* as required by write.
// 3) pass the size of the pointer to member
// and you should write the values printed out.
// Note the values may be non printable but I am sure you can work with that
// Also note the meaning is not useful to you as it is compiler dependent.