指针语义
ฅ'ω'ฅ♪

指针语义

首先观察以下代码

#include <bits/stdc++.h>
using namespace std ;

class A
{       
public:
    int arr[100] ;
    void foo() {
        cout<<"A:"<<arr[10]<<'\n' ;
    }
};

class B
{       
public:
    int arr[1] ;
    void foo() {
        cout<<"B:"<<arr[10]<<'\n' ;
    }
};

signed main(int argc, char const *argv[])
{
    A a ;
    for (int i=0 ; i<100 ; ++i) {
        a.arr[i] = 0 ;
    }
    a.arr[10] = 121 ;

    void *pt1 = &a ;
    pt1->foo() ;

    B *pt2 = reinterpret_cast<B *>(pt1) ;
    pt2->foo() ;
    for (int i=10 ; i<=10 ; ++i) {
        pt2->arr[i] = 122 ;
    }
    pt2->foo() ;
    cout<<pt2<<endl ;

    A *pt3 = reinterpret_cast<A *>(pt1) ;
    pt3->foo() ;
    a.foo() ;
    cout<<pt3<<endl ;

    return 0;
}

思考如下几个问题:

  1. L18 能否通过编译,为什么?
  2. L31 能否通过编译,为什么?
  3. L36 能否通过编译,为什么?
  4. pt2 == pt1?
  5. 去除L31,依次的输出会是怎么样的?为什么?

问题1:

当然能通过编译,因为arr[10]==*(arr+10),而且在编译时期编译器会先“观察”class的全部之后,再进入member function的内部进行分析。所以编译器并不能发现foo()内所操作的内存大小“对不上”B应该能操作的大小。

问题2:

不行,原因于void *的语义有关,这个在下面解释。

问题3:

同问题1。

问题4:

true

问题5:

输出应该是

121

122

122

122

指针语义

一个指针做存放的是某个地址,指向一个变量或为空。

实际上,这个说法或者类似的说法都过于浅薄了。

一个指针变量除了保存了某个地址外,还拥有自身的type 。

这看起来是一句废话,但是这是解释问题2的关键。

“指向不同类型之各指针”之间的差异,既不在其指针表示法不同,也不再其内容不同,而是在其所寻址出来的object类型不同。也就是说,“指针类型”会教导编译器如何解释某个特定地址中内存内容及其大小。

所以!一个指向地址1000而类型为void *的指针,将涵盖怎样的地址空间?没有人会知道。编译器也无从得知,这就是为什么一个void *指针 只能持有一个地址,而不能通过它操作所指的obj 的缘故。

在这种观念下,指针所拥有的内容(地址)反而不太重要了,重要的是指针类型会影响“所指出的内存的大小及其内容”的解释方式。指针的“相互转移”,不会引发内存中任何“与类型相关的内存委托操作”,只改变自身所指向内存的“大小和解释方式”而已。

而以上,也是C++实现多态的基础之一。

结束

而对于输出的顺序,根据以上的指针语义。

pt1被转换为类型为 B * 的pt2,此时通过pt2读取的仍然是a的空间,而arr[100]是非静态成员数据,存储在a中,所以pt2所访问到的是a的arr[10],而不是B::arr[10],也不会报错。

pt2对于arr[10]的修改能“延续”到pt3和a处也是一样的道理,操作的内存是同一块。

但是,pt2为什么能调用到B::foo()而不是A::foo()呢。

A::foo(),B::foo()都是非静态非虚拟成员函数,所以他们拥有与普通函数一样的效率和语义。

在我们眼里他们是同名函数,但是在编译器眼中就可能是如下模样

void
foo__1AVF(const A *const this){...}
void
foo__1BVF(const B *const this){...}

这就是于指针类型有关了,指针类型不光“指导”编译器从pt1处解释多大的空间,还会根据这个类型去“寻找”匹配的foo()函数。

根据B *很容易就能找到B::foo()并调用,只是其中的arr[10]仍然是A::arr[10],因为指针所指地址在那,所解释空间也没问题。

CANCEL

-评论-

Here you can post what you want to say, if you have more information please contact me by the following way.

-昵称-
-QQ-
-邮箱-
想说些什么?
-SUBMIT-

-电联 Phone-

+86 18520664652

-邮箱 Email-

boogieLing_o@163.com

boogieLing_o@qq.com

Your name. OS platform Browser model

What do you want to say?

created time

游說萬乘苦不早,著鞭跨馬涉遠道。

阿凌的貓爬架

幸會,

激活Ubuntu

转到“设置”以激活Ubuntu。

R0's board.