C++ 这是C++;代码可移植?

C++ 这是C++;代码可移植?,c++,compiler-construction,virtual,portability,C++,Compiler Construction,Virtual,Portability,所有这三个g++、vs2010和clang调用B::print。几乎怀疑我的C++ 101。我的印象是,在对象上使用点不会导致动态调度。只有带有指针的->和带有引用的点将导致动态分派 所以我的问题是这个代码是否是可移植的?a[0]与*a相同,这个表达式是对a的引用,虚拟调度通过引用进行,就像通过指针进行一样a->print()和(*a).print()完全相同。它是便携式的。[0]返回引用,引用也使用动态分派。是。相当于- struct A { int a; virtual void p

所有这三个g++、vs2010和clang调用B::print。几乎怀疑我的C++ 101。我的印象是,在对象上使用点不会导致动态调度。只有带有指针的->和带有引用的点将导致动态分派


所以我的问题是这个代码是否是可移植的?

a[0]
*a
相同,这个表达式是对
a
的引用,虚拟调度通过引用进行,就像通过指针进行一样
a->print()
(*a).print()
完全相同。

它是便携式的。[0]返回引用,引用也使用动态分派。

是。相当于-

struct A {
  int a;
  virtual void print() {}
};

struct B : A {
  int b;
  virtual void print() {}
};

int main(void)
{
  A *a = new B;
  a[0].print(); // g++, vs2010, clang call B::print.
}

它是可移植的,并且行为定义明确<指针上的代码>运算符[]只执行指针算术和解引用。它将
0*sizeof(A)
添加到指针,因此从某种意义上讲,这是一个“危险”的操作,因为任何其他值都会失败,但是0*sizeof(A)是0,在这种情况下,您可以,因为它添加了0


多态性既适用于引用,也适用于指针。

使用带有指针的
a[0]
定义良好,其含义与
*(a+0)
相同。这就是内置的
[]
操作符的工作原理

在没有多态性的情况下,编译器不需要使用动态调度,这在一定程度上是正确的。这只是一种常见的优化,而不是语言所要求的

当代码是

a->print();

编译器可以直接调用正确的函数,因为它可以在编译时告诉对象类型。

是的,为什么引用不能用于动态分派?这与可移植性没有什么关系,但它是可移植的。虚拟分派通过指针和引用进行。您可能想提到的是,
a[0]
实际上相当于
*(a+0)
,而
(*a)
。假设没有发生运算符重载,数组下标就是这样计算的。@InSilco:不,等等,
a
有指针类型,不能重载指针的运算符。
a*a=new B
A*A=新的B[1]
除了在前者上使用
delete
和在后者上使用
delete[]
之外?@SethCarnegie:我不这么认为。后者返回指向第一个(也是唯一一个)元素的指针,前者只返回指向对象的指针。。。看起来它们几乎一样(假设底层分配函数中没有hocus pocus)。@Insilico:没错。如果这不是C++,而是CSS,那么<代码> [HRFF] 将是元素选择器,而 *> A <代码>将匹配所有锚。我对某种事物感到好奇。我无法想象一个实现会不起作用,但是
a[0]
*(a+0)
;里面有指针算法。我认为指针算法是未定义的行为,如果指向对象的动态类型不同于静态类型,这里就是这种情况。是的(有点),但我很难看出
a+0
可能不同于
a
。标准中可能未提及。:-)另一方面,我不希望有关
a+0
的规则与有关
a+1
:-)的规则有所不同。(我不喜欢特殊情况。)在实践中,当然,当没有未定义的行为时,
a+0
必须等于
a
,并且我看不到在理论上存在未定义的行为时实现会有所不同。
A a;
a.print();