指向成员的指针如何知道它绑定哪个成员?

时间:2018-01-04 04:14:50

标签: c++ c++11 pointers clang c++14

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而不是value1value3只是因为你通过了&Sample::value2

我的猜测: 我认为&Sample::value2必须是特殊的,以指示指针var应指向地址偏移 2 double。但关键是如何表明?我没有在clang AST中找到任何其他信息。请帮我。 THX。

2 个答案:

答案 0 :(得分:1)

  

所以我的问题是这个指针(var)如何知道它绑定到value2而不是value1或value3只是因为你传递了&amp; Sample :: value2?

因为那是&Sample::value2传递的内容。

这里的关键点是,与大多数指针不同,指向成员的指针不是指内存位置,而是指某个内部编译器定义的状态,指向它引用的类型的成员。

实际上,这通常只是指相对于this的字节偏移量。

答案 1 :(得分:1)

在典型的实现中,指向数据指针的类型的指针完全按照您的猜测实现:它是从包含对象的开头以字节为单位的偏移量。

在您的示例中,var将实现为Sample对象开头的偏移量(以字节为单位)。假设sizeof(double)8并且字段之间没有填充,则var初始化为&Sample::value2实际上只是伪装偏移8&Sample::value10&Sample::value316

这种实现方法的一个奇怪结果是值0对于这样的指针也是一个“有用的”值(对于第一个字段偏移0),这意味着这个空指针的值kind不能用全零位模式表示。通常,实现在这样的指针中使用0xFF...F模式作为空指针表示。