c++学习
#include<iostream> int main() { std::cout<<"test \n"; int sjk; std::cin>>sjk; std::cout<<sjk; return 0; }
#include <iostream> //using std::cout; //using std::endl; using namespace std; int main() { cout<<"test \n"; cout<<endl; return 0; }
命名空间冲突问题
#include <iostream> //using namespace std; namespace a{ int a=1; } namespace b{ int a=2; } int main() { //int a=3; using namespace a; using namespace b; std::cout<<a<<"|"<<a::a<<"|"<<b::a<<std::endl; return 0; }
函数应用
#include <iostream> using namespace std; int sum(int a, int b) { return a+b; } int main() { int a, b; cin>>a; cin>>b; cout<<"a+b="<<sum(a,b); return 0; }
函数的声明与定义
#include <iostream> using namespace std; //函数声明 //int sum(int a, int b); int sum(int, int); //参数名可以省略 int main() { int a, b; cin>>a; cin>>b; cout<<"a+b="<<sum(a,b); return 0; } //函数定义 int sum(int a, int b) { return a+b; }
#include <iostream> using namespace std; void a(); void b(); void a() { cout<<"a \n"; b(); } void b() { cout<<"b \n"; a(); } int main() { a(); return 0; }
变量范围
#include <iostream> using namespace std; int x,y;//全局变量对任何函数都有效 void change() { x=100; } int main() { change(); cout<<x; return 0; }
款字符型
#include <iostream> #include <locale> using namespace std; int main() { setlocale(LC_ALL, "chs"); wchar_t wc[] = L"中"; wcout<<wc; return 0; }
#include <iostream> #include <iomanip> using namespace std; int main() { double a=1.32545488787778575; // 有效 6~7位 //cout<<setprecision(15)<<a; const int b =1; //枚举用字母代替数字 //enum num{zero, one, two, three}; //默认从0开始计算 enum num{zero=100, one, two=300, three}; //默认从0开始计算 cout<<one; num n = zeros; if(n == zero) { cout<<"yes"; }else{ cout<<"no"; } return 0; }
类的定义与使用:
#include <iostream> using namespace std; class man{ public: void getHeight(){ cout<<height; } void getWeight(); void setWeight(int); public: int height=0; int weight; }; void man::getWeight(){ cout<<weight; } void man::setWeight(int n){ weight=n; } int main() { man p ; p.setWeight(10); p.getWeight(); return 0; }
内联函数:(函数体比较小时比较好)
#include <iostream> using namespace std; //效率更高,不必跳来跳去 //编译器不会真正的创建该函数,只是将这个函数的代码拷贝到调用的函数中,提高了效率,增大了程序的体积 inline void print(); void print() { cout<<"yes"; } class man{ public: void getHeight(); private: int height; }; void man::getHeight() { cout<<height; } int main() { //print(); man p; p.getHeight(); return 0; }
const函数
class man{ public: void getHeight(); void setHeight() const { //不想让某个成员函数修改成员变量的值 height = 5; } private: int height; };
构造函数
#include <iostream> using namespace std; class man{ public: int height; public: //注意构造函数没有返回值,不用表明返回值类型 man(int h){ height =h; } void getHeight(); void setHeight() { //不想让某个成员函数修改成员变量的值 height = 5; } }; int main() { man p(55); cout<<p.height; return 0; }
构造函数与析构函数
#include <iostream> using namespace std; class man{ public: int height; public: //注意构造函数没有返回值,不用表明返回值类型 man(int h){ height =h; } //不能有返回值和参数,有且只有一个 ~man() { } void getHeight(); void setHeight() { //不想让某个成员函数修改成员变量的值 height = 5; } }; int main() { man p(55); cout<<p.height; return 0; }
堆中创建变量和对象
#include <iostream> using namespace std; class man{ public: void getHeight(){ cout<<height; } void setHeight() { //不想让某个成员函数修改成员变量的值 height = 5; } private: int height; }; int main() { //定义时进行初始化 //int *p=0; int *p=new int; *p = 1; //变量保存在堆中 cout<<*p; delete p; p=0; man *p1 = new man; (*p1).setHeight(); // 或 p1.setHeight(); (*p1).getHeight(); delete p1; p1=0; return 0; }
//堆栈内存中变量的释放
#include <iostream> using namespace std; class man{ public: man(){ cout<<"construct \n"; } ~man(){ cout<<"destruct \n"; } }; int main() { //在栈中分配的系统帮你释放 man person ; //在堆中分配的要手动释放 man *p=new man; delete p; return 0; }
this指针
#include <iostream> using namespace std; class man{ public: man(int sex){ //this指针指向当前对象,由编译器来删除 this->sex=sex; //解决了命名冲突的问题 cout<<this<<"\n"; } int sex; }; int main() { man p(5); cout<<&p<<"\n"; cout<<p.sex<<"\n"; return 0; }
指针的释放
#include <iostream> using namespace std; int main() { int *p=new int; *p=3; cout<<p<<"\n"; delete p; p=0; //一定要 赋值为 0 int *p1=new int; cout<<p<<"\n"; //会和p1的地址一样 cout<<p1<<"\n"; *p=33; cout<<*p1<<"\n"; return 0; }
引用就是别名,是常量,必须进行初始化
#include <iostream> using namespace std; int main() { int a=1; int &b=a; //引用就是别名,地址是相同的,是常量,必须进行初始化 b=2; cout<<a<<b; cout<<&a<<"\t"<<&b; return 0; }
别名传递
#include <iostream> using namespace std; void swap1(int &a, int &b) { int c; c=a; a=b; b=c; } int main() { int a=1,b=2; swap(a,b); cout<<a<<"\t"<<b; return 0; }
按指(针)传递
#include <iostream> using namespace std; void swap(int *a, int *b) { int c; c=*a; *a=*b; *b=c; } int main() { int a=1,b=2; swap(&a, &b); cout<<a<<"\t"<<b; return 0; }
值传递对象的开销
#include <iostream> using namespace std; class man{ public: man(){cout<<"construct \n";} man(man&){cout<<"copy \n";}//在栈中创建临时对象的拷贝时调用 ~man(){cout<<"destruct \n";} }; man test(man one) { return one; } int main() { man p; test(p); return 0; } /** construct copy copy destruct destruct destruct 请按任意键继续. . . */
优化1
#include <iostream> using namespace std; class man{ public: man(){cout<<"construct \n";} man(man&){cout<<"copy \n";}//在栈中创建临时对象的拷贝时调用 ~man(){cout<<"destruct \n";} }; man test(man *one) { return *one;//按值返回,会返回对象的副本 } int main() { man p; test(&p); return 0; }
优化2(指针方式传递)
#include <iostream> using namespace std; class man{ public: man(){cout<<"construct \n";} man(man&){cout<<"copy \n";}//在栈中创建临时对象的拷贝时调用 ~man(){cout<<"destruct \n";} }; man* test(man *one) { return one;//按值返回,会返回对象的副本 } int main() { man p; test(&p); return 0; }
按值传递增加const(增加包含机制)
#include <iostream> using namespace std; class man{ public: man(){cout<<"construct \n";} man(man&){cout<<"copy \n";}//在栈中创建临时对象的拷贝时调用 ~man(){cout<<"destruct \n";} int a; }; const man* const test(const man *const one) { return one; } int main() { man p; const man * const p1 = test(&p); p1++; return 0; }
引用于指针
#include <iostream> using namespace std; class man{ public: man(){cout<<"construct \n";} man(man&){cout<<"copy \n";}//在栈中创建临时对象的拷贝时调用 ~man(){cout<<"destruct \n";} int a; }; const man& test(const man &one) { cout<<&one<<"\n"; return one; } int main() { int *p=new int; *p=2; int *&r=p;//指针的别名 //int &r=*p;//指针的值别名 cout<<*p<<endl; cout<<*r<<endl; //cout<<r<<endl; }
#include <iostream> using namespace std; int main() { int *&p=new int; *p=13; }
引用与指针,返回时的内存释放情况
#include <iostream> using namespace std; class a{ public: a(int x){ this->x=x; } a(a &b){this->x=b.x;cout<<"copy";} public: int x; }; a test1() { //如果引用是一个临时变量副本,那么这个临时变量的生存期会不少于这个引用的生存期。 a b(10); return b; //返回的并非 b对象,而是其副本 } a& test2() { a b(11); //返回局部变量或临时变量的地址 return b; } int main() { a b = test1(); //right a *b = &test1(); //如果用指针来接收则不对,副本的内存地址会被立刻释放(但里面的数据可能没有被清楚,所以看起来仍旧是对的) cout<<b.x<<endl; }
返回对象副本导致内存泄露
#include <iostream> using namespace std; class a{ public: a(int x){ this->x=x; } a(a &b){this->x=b.x;cout<<"copy";} public: int x; }; a test() { a *p =new a(10); return *p; //返回的对象的副本(分配到栈上),而 p被释放了,会出现内存泄露 //要解决内存泄露就不能反悔对象副本,而是返回指针或别名 } int main() { a &b = test(); /* 这种是错误的,只有栈上的空间采用delete释放 a *p = &b; delete p; p=0; */ cout<<b.x<<endl; }
解决上面的问题:
#include <iostream> using namespace std; class a{ public: a(int x){ cout<<"constuct"<<endl; this->x=x; } a(a &b){this->x=b.x;cout<<"copy";} ~a() { cout<<"destruct"<<endl; } public: int x; }; a& test() { a *p =new a(10); cout<<p<<endl; return *p; } int main() { a &b = test(); cout<<b.x<<endl; cout<<&b<<endl; a *p = &b; delete p; p=0; //注意 此时b别名已经不可以再使用了 }
函数、方法都支持重载,默认值
#include <iostream> using namespace std; void test(int a, int b=3) { cout<<a<<" "<<b<<endl; } void test() { cout<<"haha"<<endl; } int main() { test(); test(5); test(5,55); return 0; }
成员变量赋初值
#include <iostream> using namespace std; class man{ public: //man():age(10),sex(1){} man(){age=10;sex=1;} //man(int age=10,int sex=1) {this->age=age; this->sex=sex;} public: int age; int sex; }; int main() { man son; cout<<son.age<<endl; return 0; }
成员变量的初始化
#include <iostream> using namespace std; class man{ public: man():age(10),sex(1){} //初始化 public: const int age; //@notice cosnt int sex; }; int main() { man son; cout<<son.age<<endl; return 0; }
#include <iostream> using namespace std; class man{ public: explicit man(int x){age=x;cout<<"consctruct"<<endl;} //关闭类型转换的特性 void setAge(int num){age=num;} void getAge(){cout<<age<<endl;;} ~man(){cout<<"desctruct"<<endl;} public: int age; }; int main() { man son(10); son.getAge(); son=100; //等价于 son = man(100); 强制类型转换,显式转换 return 0; }
复制的对象中成员变量有指针
成员拷贝,浅拷贝
#include <iostream> using namespace std; class man{ public: man(){p=new int();*p=110;cout<<"consctruct:"<<age<<endl;} man(man &a){ p=a.p; cout<<"copy:"<<age<<endl; } ~man(){cout<<"desctruct:"<<age<<endl;delete p;p=NULL;} void setAge(int num){age=num;} int getAge(){return age;} int getP(){return *p;} void setP(int x){*p = x;} public: int age; int *p; }; int main() { man *p1 = new man(); man b = (*p1); //当复制的对象的成员有指针时,指针指向的相同的内存地址,当一个对象析构时,另一个对象的指针也不可以用了 p1->setAge(55); b.setP(4); b.setAge(44); delete p1; //main函数执行完毕后,会释放 b,再次执行 析构函数释放p,但此时p已经为空,则程序会崩溃 cout<<p1->getP()<<endl; cout<<p1->getAge()<<endl; return 0; }
深层拷贝
#include <iostream> using namespace std; class man{ public: man(){p=new int();*p=110;cout<<"consctruct:"<<age<<endl;} man(const man &a){ //增加const更好 p = new int(); *p = *(a.p); cout<<"copy:"<<age<<endl; } ~man(){cout<<"desctruct:"<<age<<endl;delete p;p=NULL;} void setAge(int num){age=num;} int getAge(){return age;} int getP(){return *p;} void setP(int x){*p = x;} public: int age; int *p; }; int main() { man *p1 = new man(); man b = (*p1); //当复制的对象的成员有指针时,指针指向的相同的内存地址,当一个对象析构时,另一个对象的指针也不可以用了 p1->setP(22); cout<<p1->getP()<<endl; // 22 cout<<b.getP()<<endl; // 默认值 110 b.setP(44); cout<<p1->getP()<<endl; // 22 cout<<b.getP()<<endl; // 44 delete p1; cout<<b.getP()<<endl; // 44 删除p1后b不受影响 return 0; }
运算符重载
#include <iostream> using namespace std; class num{ public: num(){x=1;} int getX(){ return x; } void setX(int x) { this->x = x; } //运算符重载 void operator++(){ x++; } private: int x; }; int main() { num a; ++a; // 等价于 a.operator++(); //num j=++a; 这样是错误的相当于 j=a.operator++(), 而其没有返回值 cout<<a.getX()<<endl; }
解决上面的问题(创建临时对象)
#include <iostream> using namespace std; class num{ public: num(){x=1;} int getX(){ return x; } void setX(int x) { this->x = x; } //运算符重载 num operator++(){ x++; num tmp ; tmp.setX(x); return tmp; } private: int x; }; int main() { num a; ++a; // 等价于 a.operator++(); num j=++a; cout<<j.getX()<<endl; }
创建对象的3种方式:
#include <iostream> using namespace std; class A { private: int n; public: A(int m):n(m) { } ~A(){} }; int main() { A a(1); //栈中分配 隐式调用 A b = A(1); //栈中分配 显式调用 A* c = new A(1); //堆中分配 delete c; return 0; }
创建无名临时对象
#include <iostream> using namespace std; class num{ public: num(){x=1;} num(int x){this->x=x;} int getX(){ return x; } void setX(int x) { this->x = x; } //运算符重载 num operator++(){ x++; return num(x); } private: int x; }; int main() { num a; ++a; num j=++a; cout<<j.getX()<<endl; }
重载赋值运算符
#include <iostream> using namespace std; class num{ public: num(){x=1;cout<<"construct"<<x<<endl;} num(int x){this->x=x;cout<<"construct:"<<x<<endl;} ~num(){cout<<"destruct:"<<x<<endl;} num(num &a){this->x=a.x;cout<<"copy:"<<x<<endl;} int getX(){ return x; } void setX(int x) { this->x = x; } //运算符重载 num operator+(num &r){ return num(x+r.getX()); } void operator=(num &r){ cout<<"operator+"<<endl; } private: int x; }; int main() { num a(11),b(22); b = a; return 0; }