这个野指针不?为什么可以使用?

方紫涵 2012-10-23 02:40:01

#include<iostream>
#include<cstring>

using namespace std;

class A
{
public:
void prinfs()
{
cout<<"aaaaa"<<endl;
}
};



int main( )
{
A *a;
a->prinfs();
return 0;
}


A *a;
a->prinfs(); //这个a是个野指针不?为什么能够执行阿?

在g++里面

work/ctest$ g++ array.cpp -o 1
/work/ctest$ ./1
aaaaa
...全文
3201 83 打赏 收藏 转发到动态 举报
写回复
用AI写文章
83 条回复
切换为时间正序
请发表友善的回复…
发表回复
jilianglijie 2012-11-05
  • 打赏
  • 举报
回复
楼主我的理解如下: 对类方法的调用是直接对类中函数的调用; 对象对类中数据的方法是通过指针的方法进行访问的; 就以你的代码为例

#include<iostream> 
#include<cstring>
 
using namespace std;
 
class A
{
public:
    void prinfs()
    {
        cout<<"aaaaa"<<endl;
    }
};

int main( )
{
    A *a;
    a->prinfs();
    return 0;
}
其中调用a->printfs();其实是对该类中方法的直接调用,而你没有直接使用到this指针因此系统不报错。 我有以下佐证(windows下验证):

	A *a;
	a->prinfs();
004114E5  cmp         byte ptr [ebp-0D1h],0 
004114EC  jne         wmain+3Bh (4114FBh) 
004114EE  push        offset  (411519h) 
004114F3  call        @ILT+250(__RTC_UninitUse) (4110FFh) 
004114F8  add         esp,4 
004114FB  mov         ecx,dword ptr [a] 
004114FE  call        Printer::Printer (411267h) 
以上是执行a->printfs();的汇编代码,当然在这段代码中是会出错的,由于没有进行初始化因此编译器执行__RTC_UninitUse来进行检查,所以代码执行到这就会发生异常,但继续执行还是可以输出‘aaaaa’。 我后来给指针赋值为NULL汇编代码如下

	A *a= NULL;
004114DE  mov         dword ptr [a],0 
	a->prinfs();
004114E5  mov         ecx,dword ptr [a] 
004114E8  call        Printer::Printer (411267h) 
执行过程没有发生异常,可以看到寄存器ecx中保存的即时对象指针。 因此你要的答案是: 是野指针。因为调用对象的方法是直接调用类中函数的方法来实现的,在这个例子中是可以使用的。 提示: 如果你在该方法中使用了类中的其他成员变量,则会造成不可预期的错误。建议修改此类错误。
ysu108 2012-11-05
  • 打赏
  • 举报
回复
函数是是属于整个类的,并不是某个对象的,就跟static变量一样。这样使用没有涉及到this的解引用,函数没有使用任何数据成员,可以直接调用的~
再见理想~ 2012-11-05
  • 打赏
  • 举报
回复
没法运行,野指针
Vonger 2012-10-29
  • 打赏
  • 举报
回复
其实也没什么,C++的函数都是导出成类似C的符号使用的,所以你那个不仅能编译还能运行
你的A下的print在编译后obj内其实是一个类似于这样的C函数 A_print(void, void *this)
这个可以用dependswalker之类的工具查看C++封装的DLL就可以看到
函数里面没有用到this指针,所以也就不存在什么野指针,照样不会崩溃
俯瞰夕阳 2012-10-28
  • 打赏
  • 举报
回复
好多大神啊
江南刹 2012-10-28
  • 打赏
  • 举报
回复
指针最忌讳没有赋值就开始用了,int *p;
cout<<*p<<endl;
由于p指向的空间内容未知不确定,所以。。。
渔丶 2012-10-27
  • 打赏
  • 举报
回复
受教了,!各位大神论述的很清楚!
方紫涵 2012-10-27
  • 打赏
  • 举报
回复
这个砖头引来这么多玉阿!
Tyun2012 2012-10-27
  • 打赏
  • 举报
回复
8楼+25楼的理论说得比较清楚了,貌似53楼的代码解说不错,不过确实说得蛮乱。就你的问题回答,那是个野指针,一般编译器都能运行。简单说,野指针也是个指针,只是指向的目标不明确,是一片无意义的内存空间。要是编译器严格点,就可能报错,一般都不会的。
这样做是很危险的,就像拿一把枪,乱扫一样!指不定哪儿有个人,就被你打死了!
ganjianh8 2012-10-27
  • 打赏
  • 举报
回复
看我的博客
帅虫虫 2012-10-27
  • 打赏
  • 举报
回复
成员函数(不含静态成员函数)和普通函数的区别就在于成员函数有一个隐藏的参数this。
你代码中的成员函数里(prinfs)里没有访问this指针,自然就不会报错。
yzh198769 2012-10-27
  • 打赏
  • 举报
回复
这样写很不规范
bean11222 2012-10-27
  • 打赏
  • 举报
回复
这个很好理解,因为你只申明了一个指针变量(32位是4字节, 可以把它当整型看都没问题),而指针变量所指向的对象并没有初始化。。。。
已毕业程序员 2012-10-26
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

引用 2 楼 的回复:

是野指针。
你只是生命了一个指针,却没有给它分配内存空间。
C/C++ code

int main( )
{
A *a = new A();
a->prinfs();
delete a;
return 0;
}

看我的运行结果,并没有new一个实例出来阿,但是确实是可以运行的阿/
[/Quote]

你已经new出一个实例了,一个无名的实例,当然可能运行
我爱吃火锅 2012-10-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

是野指针。
你只是生命了一个指针,却没有给它分配内存空间。
C/C++ code

int main( )
{
A *a = new A();
a->prinfs();
delete a;
return 0;
}
[/Quote]
二楼说的对,确实是野指针。
yisikaipu 2012-10-26
  • 打赏
  • 举报
回复
[Quote=引用 60 楼 的回复:]

引用 59 楼 的回复:
If E1 has the type “pointer to class X,” then the expression E1->E2 is converted to the equivalent form (*(E1)).E2;
意思是 a->prinfs(); 其实是要转换为 (*a).printfs();
呃 这里应该没有表达要转换为的意思
不过 的确……
[/Quote]

不妨用 call a member function on a null pointer 搜搜,不难发现网上但凡读标准的,都认为用空指针调用成员函数是未定义行为。换成野指针/悬垂指针,道理类似

lin5161678 2012-10-26
  • 打赏
  • 举报
回复
[Quote=引用 59 楼 的回复:]
If E1 has the type “pointer to class X,” then the expression E1->E2 is converted to the equivalent form (*(E1)).E2;
意思是 a->prinfs(); 其实是要转换为 (*a).printfs();[/Quote]
呃 这里应该没有表达要转换为的意思
不过 的确说了 两者是等价的
那么 a->.... 和 (*a)....表达的应该是一样的
能写成a->的就能写成(*a).的形式
(*a). 有一个对指针*求值的操作 嗯 的确是看到未定义行为了
恩恩 同意你的看法 未定义行为
yisikaipu 2012-10-26
  • 打赏
  • 举报
回复
[Quote=引用 58 楼 的回复:]

看了半天 觉得 这里主要的问题就是
一个类的不同对象的同一个成员函数是不是在一个位置
如果这个在标准中有明确指出的 是同一个函数
那么 A* a;a->print();就应该没什么问题
[/Quote]

诸如这样的写法
((A*)0)->printfs()
的确是很常见的,但不合标准

我在#40楼给出了标准有关这种行为的规定

如果我理解错了,请一定给指正
lin5161678 2012-10-26
  • 打赏
  • 举报
回复
看了半天 觉得 这里主要的问题就是
一个类的不同对象的同一个成员函数是不是在一个位置
如果这个在标准中有明确指出的 是同一个函数
那么 A* a;a->print();就应该没什么问题
lanzhengpeng2 2012-10-26
  • 打赏
  • 举报
回复
因为prints()不是虚函数,所以,用C表达就是
A::prints(A*this)调用。是在编译时刻决定的调用哪个函数。而你在prints()并没有访问this,所以,也不会出一场。
如果prints是virtual的,则,用C表达就是
a->vtable[prints_index](A* this).
这样,因为在求vtable的时候,a是野指针,就会导致异常。
加载更多回复(62)

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧