struct Sample {
double value1;
double value2;
double value3;
};
double Mean(std::vector<Sample>::const_iterator begin,
std::vector<Sample>::const_iterator end,
double Sample::* var)
{
float mean = 0;
int samples = 0;
for(; begin != end; begin++) {
const Sample& s = *begin;
mean += s.*var;
samples++;
}
mean /= samples;
return mean;
}
...
double mean = Mean(samples.begin(), samples.end(), &Sample::value2);
来自C++: Pointer to class data member “::*”
的代码副本我认为这是展示何时以及如何使用指向成员的指针的一个很好的示例,但在深入之后,我发现var
的类型是double Sample::*
。
所以我的问题是这个指针(var
)如何知道它绑定到value2
而不是value1
或value3
只是因为你通过了&Sample::value2
?
我的猜测:
我认为&Sample::value2
必须是特殊的,以指示指针var
应指向地址偏移 2 double
。但关键是如何表明?我没有在clang AST中找到任何其他信息。请帮我。 THX。
答案 0 :(得分:1)
所以我的问题是这个指针(var)如何知道它绑定到value2而不是value1或value3只是因为你传递了&amp; Sample :: value2?
因为那是&Sample::value2
传递的内容。
这里的关键点是,与大多数指针不同,指向成员的指针不是指内存位置,而是指某个内部编译器定义的状态,指向它引用的类型的成员。
实际上,这通常只是指相对于this
的字节偏移量。
答案 1 :(得分:1)
在典型的实现中,指向数据指针的类型的指针完全按照您的猜测实现:它是从包含对象的开头以字节为单位的偏移量。
在您的示例中,var
将实现为Sample
对象开头的偏移量(以字节为单位)。假设sizeof(double)
为8
并且字段之间没有填充,则var
初始化为&Sample::value2
实际上只是伪装偏移8
。 &Sample::value1
为0
,&Sample::value3
为16
。
这种实现方法的一个奇怪结果是值0
对于这样的指针也是一个“有用的”值(对于第一个字段偏移0
),这意味着这个空指针的值kind不能用全零位模式表示。通常,实现在这样的指针中使用0xFF...F
模式作为空指针表示。