如何检查两个指针​​是否指向同一个对象?

use*_*672 14 c++ dynamic-cast

考虑两个指针

A* a; 
B* b;
Run Code Online (Sandbox Code Playgroud)

A和B都是多态类.如何检查a和b是否指向同一个对象?

更确切地说,如果存在类型D的某个对象d,则指定a和b指向同一对象,使得*a和*b都在d的类层次结构中的某处.

我建议以下解决方案:

dynamic_cast<void*>(a) == dynamic_cast<void*>(b)
Run Code Online (Sandbox Code Playgroud)

的确,根据标准,

dynamic_cast<void*>(v) 
Run Code Online (Sandbox Code Playgroud)

产生"指向v.指向的最派生对象的指针(n3242.pdf:§5.2.7 - 7).如果两者的派生最多是同一个对象,则指针指向同一个对象.

从实际角度来看,我很确定它应该始终正常工作.但理论上,乍一看提议的平等似乎会产生假阳性,例如,如果b指向A的第一个成员(不是A的祖先).虽然实际上不可能为A及其成员获取相同的地址,因为A的虚拟表指针应位于此成员之前,因此该标准不强制要求虚拟表,也不对类布局说明任何内容.

所以,我的问题是:

  1. 从标准角度来看,建议的解决方案是否正确?

  2. 有关私人(受保护)继承或cv资格的任何警告吗?

  3. 有更好的解决方案吗?

[编辑]

我试图提供一些例子来说明一个相对复杂的场景.在这种情况下,动态横向铸造和静态铸造是模糊的.

 // proposed impplementation:
template<typename P, typename Q> 
bool test_ptrs(const P* p, const Q* q)
{
  return (dynamic_cast<const void*>(p) ==  dynamic_cast<const void*>(q));
}


struct Root
{
  virtual ~Root(){};
};

struct A: public Root // nonvirtually
{
};

struct B: public Root // nonvirtually
{
};

struct C: public A, B  // nonvirtual diamond started with Root
{
  Root another_root_instance;
};

int main()
{
  C c;

  A* pa= &c;
  B* pb= &c;

  bool b = (dynamic_cast<void*>(pa) ==  dynamic_cast<void*>(pb));

  Root* pra= dynamic_cast<Root*> (pa); 
  Root* prb= dynamic_cast<Root*> (pb);

  //Root* prc= dynamic_cast<Root*> (&c); // runtime error, ambiguous cast
  Root* prr= dynamic_cast<Root*>(pra);

  Root* pcar= dynamic_cast<Root*>(pra);
  Root* pcbr= dynamic_cast<Root*>(prb);

  if(
      test_ptrs(pa, pb) 
      && test_ptrs(pra, prb)
      && !test_ptrs(pa,&c.another_root_instance)
    )
  {
    printf("\n test passed \n");
  }
}
Run Code Online (Sandbox Code Playgroud)

AKN*_*AKN 1

我试图通过比较这些指针指向的地址来解决这个问题。

  • 它所指向的地址根据指针的类型而变化。

因此理论上我们可以说

如果存在某个类型为 C 的对象 c,并且 *a 和 *b 都位于 C 的类层次结构中的某个位置,则 a* 和 b* 指向同一个对象。”

逻辑上

我们必须重新审视上面的语句,例如“a * 和 b * 指向同一个对象,但在类型 C 的 obj c 的内存中拥有自己的访问区域,因此 *a 和 *b 都位于 C 类层次结构中的某个位置C。””

struct Aa { int a; Aa() {a= 0;} };

struct Bb 
{   int b;
    Bb() { b= 0;}
}; 
struct C: Aa, Bb {      
}; 

C c; 
Aa *a1 = &c; 
Aa *a2 = &c; 
Bb *b1 = &c; 
Bb *b2 = &c; 

cout  << &c << "\t"<< &(*a1)<<"\t"<< &(*a2)<<endl;
cout  << &c << "\t"<< &(*b1)<<"\t"<< &(*b2)<<endl;
Run Code Online (Sandbox Code Playgroud)

输出:

  • &c 0x0012fd04
  • &(*a1) 0x0012fd04
  • &(*a2) 0x0012fd04
  • &(*b1) 0x0012fd08
  • &(*b2) 0x0012fd08

虽然这不能解决您的问题,但我们在这里可以推断出一点。