1

有人可以告诉我(*ptr).field和之间有什么不同ptr->field吗?我知道它以某种方式连接到静态和动态链接,但我不知道它是什么。有人可以告诉我不同​​之处并举个例子吗?

编辑:如果我有这个代码:

Point p;       //point is a class that derive from class shape 
Shape *s=&p; 
               //there is a diffrence if i write:

(*s).print();  //print is virtual func
s->print();    // the answers will not be the same, why?

天呐!

4

8 回答 8

7

这与静态或动态链接无关。

请参阅C++ 的运算符优先级。的.优先级低于,因此和*之间实际上存在很大差异。例如,以下代码演示:*ptr.fldptr->fld

#include <iostream>

struct foo {
  int f;
};

int main() {
  struct foo *p = new struct foo;
  p->f = 42;
  std::cout << p->f << std::endl;
  std::cout << (*p).f << std::endl;
  // The following will not compile
  // std::cout << *p.f << std::endl;
}

正如约翰·诺勒(John Knoeller)指出的那样,ptr->fld是 的语法糖(*(ptr)).fld,但与*ptr.fld实际评估为 的不同*(ptr.fld),可能不是您想要的。

ptr->fld当您有一个指向结构的指针并想要访问其中包含的字段时, 您会使用它。(*(ptr)).fld意思是一样的,但不那么整洁。*strct.fld当您有一个结构而不是指向结构的指针时,您将使用该结构包含一个字段 ( fld),该字段是您要取消引用的指针。的情况ptr->fld如上图所示。的情况下*strct.fld可以使用以下结构:

struct foo {
  int *fld;
}

struct foo f;
f.fld = new int;
*f.fld = 42;
于 2009-12-28T20:04:29.957 回答
4

它与静态或动态链接无关,两个表达式都将返回 ptr.field 的值

ptr->field 形式是一种缩写语法,用于直接从指针访问成员

更新:在我看来, 如果这确实是您的目标,那么您的原始意图不是链接而是绑定,那么静态绑定动态绑定 与 -> 运算符 有关,请参见此处

于 2009-12-28T19:54:22.680 回答
2

静态链接是链接器将程序中使用的所有库例程复制到可执行映像中的结果。与动态链接相比,这可能需要更多的磁盘空间和内存,但速度更快且更便携,因为它不需要在运行它的系统上存在库。

动态链接是通过将可共享库的名称放在可执行映像中来完成的。在运行映像之前,不会发生与库例程的实际链接,此时可执行文件和库都放置在内存中。动态链接的一个优点是多个程序可以共享库的一个副本。

但这与您提到的指针间接无关-实际上,这两个表达式是相同的。

于 2009-12-28T19:55:45.840 回答
2

我假设*ptr.field你的意思是(*ptr).field

就仅考虑内置运算符而言,两者之间没有区别。不,它与“静态”或“动态”链接无关,无论这些术语暗示什么。

两者之间唯一的潜在区别是,在ptr->field变体->中是 C++ 中的可重载运算符,而在(*ptr).field变体中只有*可重载,而.不是。

此外,这两种成员访问方法之间的一些差异存在于非常古老的 C 语言 (CRM C) 版本中,但我怀疑今天是否有人关心这些。

于 2009-12-28T20:04:01.443 回答
1

这与链接无关。

ptr->fld 

只是简写

(*ptr).fld

它是纯语法糖;)

于 2009-12-28T20:01:00.797 回答
1

只要ptr是一个指针,一旦正确括起来,两者就是等价的(正如其他人所说)。Ifptr是一个对象,而不是一个指针,它们可能会有所不同,具体取决于对象的类或祖先的定义operator*operator->(如果有的话)。

于 2009-12-28T20:04:27.623 回答
1

形式 -> 只是取消引用指针和访问成员的简写。

(*ptr).field;
// Equiv to 
ptr->field;

使用 -> 的一个很好的理由是,当您关注一个链时:

int x = (*(*(*(*ptr).field1).field2).field3).field4;
// Equiv to 
int y = ptr->field1->field2->field3->field4;

第二个变得更具可读性。

至于你问题的第二部分。
我发现举个例子真的很容易。

#include <iostream>

class Shape
{
    public:   virtual ~Shape()        {}
              virtual void Print()    {std::cout << "Shape\n";}
};
class Point: public Shape
{
    public:   virtual void Print()    {std::cout << "Point\n";}
};

int main ()
{
    Point   p;
    Shape*  s = &p;

    s->Print();
    (*s).Print();
}

> vi x.cpp
> g++ x.cpp
> ./a.exe
Point
Point

如您所见,两种情况下的结果是相同的。

当您通过指针或引用调用方法时,将调用虚拟调用机制。星号运算符(AKA 取消引用运算符)返回对对象的引用(它实际上并不取消引用该对象)。因此,当它用于调用方法时,将调用虚拟调用机制并调用该方法的最衍生版本。

于 2009-12-28T20:43:51.453 回答
0

他们都是一样的。
*ptr.field取消对变量的引用,ptr然后返回 member 的值field

->运算符是上述的简写符号。

于 2009-12-28T19:56:51.797 回答