char型字符串(数组)与string型字符串 指针与引用
一、常指针:
int *const p; //指针不可改变,但是指针指向的数据可以改变。
指向常量的指针:
const int *p; //指针可以改变,但是指针指向的数据不可以改变。
指向常量的常指针:
const int *const p; //指针不可改变,且指针指向的数据也不可改变。
引用就是别名,定义引用的同时必须要对引用进行初始化。
二、利用引用返回多个值:
引用就是别名,引用必须要初始化。
#include "stdafx.h" #include <iostream> #include <cmath> using namespace std; void func(int &a,int &b,int &c); int main() { int a=1; int b=2; int c=3; cout<<"主函数,计算前。。。"<<endl; cout<<a<<"\t"<<b<<"\t"<<c<<endl; func(a,b,c); cout<<"主函数,计算后。。。"<<endl; cout<<a<<"\t"<<b<<"\t"<<c<<endl; return 0; } void func(int &a,int &b,int &c) { cout<<"func函数,计算前。。。"<<endl; cout<<a<<"\t"<<b<<"\t"<<c<<endl; a=a+1; b=(b)*(b); c=(c)*(c)*(c); // cout<<"func函数,计算后。。。"<<endl; cout<<a<<"\t"<<b<<"\t"<<c<<endl; }
三、删除空指针是不会报错的。
int *p;
p=new int;
delete p;
p=0; //将指针赋值为空,假如没有这句,程序将崩溃。
delete p;
四、删除堆中指针后,只是释放了指针所指向的内存单元,指针仍然存在,且依然指向删除前的内存地址
int *p=new int(11);
cout<<"删除指针p前其指向的内存地址:"<<p<<endl;
delete p;
cout<<"删除指针p后其指向的内存地址:"p<<endl;
程序输出结果:
所以,为了保证程序的安全可靠,需要在delete p后加上p=0
五、类的对象的this指针
对象的this指针存储该对象的内存地址。
#include "stdafx.h" #include <iostream> //#include <string> //#include <limits> using namespace std; class A { private: int i; public: void set(int x){this->i=x;cout<<"this指针的指向的内存地址为:"<<this<<endl;} //也可以直接写成i=x; }; int _tmain(int argc, _TCHAR* argv[]) { A a; a.set(11); cout<<"对象的内存地址为:"<<&a<<endl; return 0; }
六、使用引用时容易犯错的地方
临时变量生存期的问题
#include "stdafx.h" #include <iostream> using namespace std; class A { private: int x; public: A(int i){x=i;} void get(){cout<<x<<endl;} ~A(){} }; A &func(); int _tmain(int argc, _TCHAR* argv[]) { A &ra=func(); ra.get(); return 0; } A &func() { A a(11); //a为临时对象,func函数一旦结束,其生存周期也结束,立即销毁 return a; }
若将func()函数前面的&去掉,则可正确返回a对象的成员变量的值。
此时函数按值返回,对象a的副本生命周期会一直持续到main()函数结束。
这是因为,作为引用的临时变量(即A &ra=func();),其生存周期不会短于该引用。
七、按值传递传递的是变量的副本,按址传递,顾名思义肯定是传送的地址了。
八、关于二维(数组)指针的一些理解问题
int ** Ptr <==> int Ptr[ x ][ y ];
int *Ptr[ 5 ] <==> int Ptr[ 5 ][ x ];
int ( *Ptr )[ 5 ] <==> int Ptr[ x ][ 5 ];
这里 x 和 y 是表示若干的意思。(转)
测试代码:
#include "stdafx.h" #include <iostream> using namespace std; int main() { int (*p)[2]=new int[2][2]; cout<<"指针数组的初始地址:"<<p<<endl; int i,j; int a[2][2]={1,2,3,4}; cout<<"二维数组的初始地址:"<<a<<endl<<endl;; cout<<"自定义赋值初始化指针数组!!!"<<endl; for (i=0;i<2;i++) for (j=0;j<2;j++) { p[i][j]=i+j; } //cout<<endl<<"使用二维数组初始化数组指针!!!"<<endl; //p=a; //使用二维数组初始化数组指针 cout<<"赋值后指针数组的地址:"<<p<<endl; for (i=0;i<2;i++) { for (j=0;j<2;j++) cout<<p[i][j]<<"\t"; cout<<endl; } delete[] p; p=0; return 0; }
下面对以上代码稍作修改,使用二维数组赋初值给指针数组。
#include "stdafx.h" #include <iostream> using namespace std; int main() { int (*p)[2]=new int[2][2]; cout<<"指针数组的初始地址:"<<p<<endl; int i,j; int a[2][2]={1,2,3,4}; cout<<"二维数组的初始地址:"<<a<<endl<<endl;; /*cout<<"自定义赋值初始化指针数组!!!"<<endl; for (i=0;i<2;i++) for (j=0;j<2;j++) { p[i][j]=i+j; }*/ cout<<endl<<"使用二维数组初始化数组指针!!!"<<endl; p=a; //使用二维数组初始化数组指针 cout<<"赋值后指针数组的地址:"<<p<<endl; for (i=0;i<2;i++) { for (j=0;j<2;j++) cout<<p[i][j]<<"\t"; cout<<endl; } //delete[] p; //p=0; return 0; }
九、复制构造函数
#include <stdafx.h> #include<iostream> using namespace std; class A { private: int m,n; public: A(int i,int j){m=i;n=j;} //构造函数 A(A&temp){m=temp.m;n=temp.n;} //复制构造函数 void print(){cout<<m<<"\t"<<n<<endl;} }; int main() { A a(2,3); a.print(); A b(a); //or A b=a;也可以 b.print(); return 0; }
#include <stdafx.h> #include<iostream> using namespace std; class A { private: int *x; public: A(){x=new int;*x=5;} ~A(){delete x;x=0;} A (const A&temp){x=temp.x;} void display(){cout<<*x<<"\t"<<&x<<endl;} void set(int i){*x=i;} }; int main() { A *a=new A; a->display(); A b(*a); b.display(); a->set(10); a->display(); b.display(); b.set(15); a->display(); b.display(); //delete a; return 0; }
深复制:(被复制对象的变量与复制对象的变量拥有各自独有的内存空间)
#include <stdafx.h> #include<iostream> using namespace std; class A { private: int *x; public: A(){x=new int;*x=5;} ~A(){delete x;x=0;} A (const A&temp){x=new int;*x=*(temp.x);} void display(){cout<<*x<<"\t"<<&x<<endl;} void set(int i){*x=i;} }; int main() { A *a=new A; a->display(); A b(*a); b.display(); a->set(10); a->display(); b.display(); b.set(15); a->display(); b.display(); delete a; return 0; }
十、char型字符串(数组)与string型字符串
如:char man[100];//当使用cin来输入字符串时,遇到空格(即空字符0 or ‘\0’)的话,字符串输出时就从此截断。
比如输入hello world,那么输出只有hello。
C++提供了一种简单高效的方法来解决上述问题,char man[]={“hello world”},或者char man[]="hello world",此时再输出就正常了。
char型字符串时C语言时的风格,在C++时代产生了C++风格的字符串,string型字符串。使用时必须添加string头文件。
由于string是一个类,那么string str;//str就可以看成是string类的一个对象,该对象可以调用string类的各种成员函数。
1、char型字符串有以下3种形式
char c[12]="study" //字符数组
“study” //未命名字符串
char *p="study" //指向未命名字符串的指针
以上3种类型只有第一种所指向的字符串可以改变。
#include "stdafx.h" #include <iostream> #include <string> using namespace std; char *get(char *str); int main() { char name[20]; char *name1; cout<<"请输入您的名字:"<<endl; cin>>name; name1=get(name); cout<<"您的名字是:"<<name1<<endl; delete []name1; name1=get("Jack"); cout<<"您的名字是:"<<name1<<endl; delete []name1; char *name2="Mike"; name1=get(name2); cout<<"您的名字是:"<<name1<<endl; delete []name1; return 0; } char *get(char *str) { char *p=new char[strlen(str)+1]; //这里如果用sizeof函数,程序会崩溃 strcpy(p,str); cout<<p<<endl; return p; }
2、C的结构体与C++的类的唯一区别在于前者的成员变量默认是公有的,而类的成员变量默认是私有的。
对于公有成员变量,我们可以像使用成员函数那样使用成员变量。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。