这是我的第一篇技术博客,浅显简短。
不多说,直接上代码:
#include <iostream>
using namespace std;
class test{
private:
int myprivateNum;
public:
test():myprivateNum(0){
cout<<"the test begin with "<<myprivateNum<<endl;
}
test(int i):myprivateNum(i){
cout<<"the test begin with "<<myprivateNum<<endl;
}
~test(){
cout<<"the test is done!\n";
}
void printsomething()
{
cout << "something\n";
}
int getMyNum(){
return myprivateNum;
}
void setMyNum(int num){
myprivateNum = num;
}
};
int main(int argc, char *argv[])
{
test* myTest = (test*)new test(3); //可以显示调用含参构造函数,注意区别
test* myTestArray = (test*)new test[10]; //动态生成数组时,会调用默认构造函数(无参),不能自己显示调用想要的含参构造函数哦~
(*myTestArray).printsomething();
(myTestArray+1)->printsomething(); //验证返回数组的头指针
test* myTestNull = NULL;
myTestNull->printsomething(); //不会出现错误,因为是静态绑定(考虑到缓存性能,编译期已经生成),所以根本没有用这个指针哦~ 函数会默认把调用它的指针当作参数传入
//myTestNull->getMyNum(); //会出现指针为空的错误
cout<<myTest->getMyNum()<<endl; //正常输出
/*
//delete后如果未清空指针,那么这段内存在未被重新使用之前也许可以正常访问;但是这段内存同样是可分配使用的,
//这就导致该指针访问相应内存时不知道这段内存存了啥二进制数据(未定义的行为);
//所以称为悬挂指针,能着地,但底下已被架空,说不定你想要着的自己家的沙发,结果落到了别人家厕所坑。
*/
delete myTest;
cout<<myTest->getMyNum()<<endl; //随机数据
myTest->setMyNum(25); //为什么依旧可以访问
//myTest = NULL; //将指针设为空后,就不能乱调用这段内存啦,所以一般指针delete后没有特殊用处的话会继续设为NULL
cout<<myTest->getMyNum()<<endl; //为什么会正常输出
delete myTest;
cout<<myTest->getMyNum()<<endl; //为什么会正常输出
return 0;
}
问题总结:
1)C++ new会返回一个指向相应实例的指针,并自动调用该实例的构造函数,如果是动态请求一个数组,则返回数组的头指针,并自动为数组每个实例调用默认构造函数。
2)C++空的类指针依旧可以调用类的函数,这是因为++类非virtual函数静态绑定的原因,在编译期就与该类绑定,之后所有该类的实例都可以共用啦,不用重新绑定缓存了,所以调用函数该根本用不到实例指针(this),非空的话也不会出现错误啦。
3)C++ delete指针后,只会把内存标记为可使用,内存在未被重新使用之前也许还能正常访问呢,delete而且不负责把指针设置为空,所以指针依旧可以访问到那段内存。
4)这就导致该指针访问相应内存时其实无法确定这段内存存了啥二进制数据(未定义的行为),所以称为悬挂指针,能着地,但底下已被架空,说不定你想要着的自己家的沙发,结果落到了别人家厕所坑。
5)一般指针delete后没有特殊用处的话会继续清空指针,即设为NULL,这样就不会乱读以及干扰那段可以被别人使用的内存啦,干净了舒服。