C++成员函数作用域问题

1.原题如下:问题是当p离开作用域时,不是应该p变成野指针么,为什么test函数输出依然正确?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
class A{
     public :
     virtual void func(){ cout << "A func()" << endl;}
};
void test(){
     A* p;
     {
         A a;
         p = &a;
     }
     p->func();
}
int main()
{
     test();
     return 0;
}

结果输出 A func()  

如下回答:

1. A的这个方法是关键。。

因为这个方法内没有访问A的任务东东。也就是没有访问this指针。因此调用有效。

如果方法中有访问A的字段就不行了。。

这是不对的,下面的代码访问到了this指针,结果依然是输出a_i值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;
class A
{
     private :
     int a_i;
     public :
     void func(){ cout << "A:a_i " << this ->a_i << endl;}
     A( int i){ this ->a_i = i;}
};
void test(){
     A* p;
     {
         A a(5);
         p = &a;
     }
     p->func();
}
int main()
{
     test();
     return 0;
}

输出为A a_i 5  

将结果换成指针的生成方式换成new,也不行,没有什么本质区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class A
{
     private :
     int a_i;
     public :
     void func(){ cout << "A:a_i " << this ->a_i << endl;}
     A( int i){ this ->a_i = i;}
};
void test(){
     A* p;
     {
         p = new A(3);
     }
     p->func();
}
int main()
{
     test();
     return 0;
}

  输出为A a_i 5 

 关于作用域:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
作用域:a.func();已经出了作用域
#include <iostream>
using namespace std;
class A{
     private :
     int a_i;
     public :
     void func(){ cout << "A:a_i " << this ->a_i << endl;}
     A( int i){ this ->a_i = i;}
};
void test(){
     A* p;
     {
         A a(5);
         p = &a;
     }
     a.func();
     p->func();
}
int main()
{
     test();
     return 0;
}

  结果:编译不过去

是不是野指针的问题,答案肯定是,看下面的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A
{
     private :
     int a_i;
     public :
     void func(){ cout << "A:a_i " << this ->a_i << endl;}
     A( int i = 0){ this ->a_i = i;}
};
int main()
{
     A* p; //野指针
     p->func();
     return 0;
}

  A 没有初始化,但是结果是: 

     A:a_i 0 

  这几天也在复习C++,想了想,其实,在C++ 对象模型 中 有这么一段话:

  类的非虚方法并不会存在于对象的内存布局中,实际上C++编译器将方法转化为全局函数,上面的会转化为: A_func_xxx (),而对象的指针是作为第一个参数被隐式的传递给了该函数,所以上面的p->func(); 调用的是全局函数A_func_xxx (),p作为this指针隐式的传递给了func()函数,所以结果是正确的

下面有一个这样的回复:

复制代码
#include <iostream>
using namespace::std;
class A
{
    private:
    int a_i;
    public:
    void func(){ cout << "A:a_i " << this->a_i << endl;}
    A(int i){this->a_i = i;}
};
void test(){
    A* p;
    {
        p = new A(3);
        delete p;
    }
    A* b=new A(23);
    cout << "==!!" << endl;
    p->func();
}
int main()
{
    test();
    return 0;
}
复制代码

   A* b=new A(23); 重新使用了先前分配的内存

下面的回复有一个关于堆栈的问题,一直以为自己懂了:

复制代码
#include <iostream>

using namespace std;

//指针的地址是在栈中(首地址除外),但是指针指向的内容却在堆中,
//所以并没有被清除

char* get_str()
{
    char* str = {"abcd"};
     return str;
}
//栈里面的变量都是临时的。当前函数执行完成时,
//相关的临时变量和参数都被清除了,所以返回的指针指向的已经是随机的了
//但是str[]首地址被当成指针来处理,存放在堆中。
char* get_str2()
{
    char str[] = {"abcd"};
     return str;
}
int main(int argc, char* argv[])
{
    char* p = get_str();
    cout << *p << endl;
    cout << *(p+1) << endl;
    cout << p << endl;
    cout << "========================" << endl;

    char *p2 = get_str2();
    //第1次执行 *p2的时候,由于p2指针的首地址被返回了,还是可以取到*p2的内容的
    /*
      可以试试取*(p2+1),也是可以取到的
    */
    cout << *p2 << endl;
   
    //第一次调用*p2的时候还是有数据的,但是第2次就没有了,
    //说明cout之后指针已经被破坏了
    cout << *p2 << endl;
    cout << *(p2+1) <<endl;
    cout << *p2 << endl;
    cout << p2 << endl;
     return 0;
}
复制代码
  但是这个:答案是可以正确的运行,因为是常量字符串,存储在静态内存区中,返回没事
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值