【问题标题】:How pointer to member know which member it bind?指向成员的指针如何知道它绑定了哪个成员?
【发布时间】:2018-01-04 04:14:50
【问题描述】:
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 只是因为你传递了 &amp;Sample::value2?

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

【问题讨论】:

  • 您是在询问一般的成员指针吗?还是 clang 的实现细节?
  • 不清楚你在问什么。它“知道”,因为您将 value2 传递给参数。
  • @vu1p3n0x clang 实现细节
  • @NirFriedman 是的,我知道我这样传递 value2。但是在Mean函数中,它只能访问类型为double Sample::*的var,var怎么知道它绑定了value2。我想知道实现细节。

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


【解决方案1】:

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

在您的示例中,var 将被实现为从Sample 对象开始的字节偏移量。假设 sizeof(double) 是 8 并且字段之间没有填充,那么用 &amp;Sample::value2 初始化的 var 实际上只是伪装的偏移 8。 &amp;Sample::value1 将是 0 和 &amp;Sample::value3 将是 16。

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

【讨论】:

  • 谢谢。所以我可以使用指向数据/函数成员类型的指针,但似乎指向重载函数成员类型的指针是非法的?因为我不能指出指针应该访问哪个函数成员。
  • 指向成员函数的指针只是函数的原始地址,但指向虚函数的指针被解释为 vtable 的偏移量,而不是对象本身。
  • @GemTaylor 重载函数不是虚函数,它不需要 vtable。
  • @merito:指向数据成员的指针和指向成员函数的指针是两个非常不同的东西。您的任务是关于指向数据成员的指针。指向成员函数的指针通常具有更复杂的内部结构,旨在使其与虚拟继承和多堆继承一起正常工作。
  • @Gem Taylor:如果您检查典型的实现,您会注意到指向成员函数的指针通常比普通的原始指针大。不,它不仅仅是原始地址,也不是 vtable 的偏移量。在所有情况下,它通常是一个指向内部调度程序函数的指针,该函数将调用重定向到正确的接收者。
【解决方案2】:

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

因为这就是传递 &amp;Sample::value2 的作用。

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

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

【讨论】:

  • 和我猜的一样,谢谢。您能否在 Clang 中提供更多实现细节?
  • 您在寻找APValue::MemberPointer,还是APValue::MemberPointerData?
  • 谢谢,这正是我要找的。​​span>
猜你喜欢
  • 1970-01-01
  • 2013-05-02
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多