C++与C的区别一

1. C++风格数组初始化:ios

#include <iostream> #include <array>

using namespace std; void main() { //CPP一维数组初始化
    array<int, 10>MyInt{ 1,2,3,4,5,6,7,8,9,10 }; for (auto i : MyInt) { cout << i << " " << (void *)&i << endl; } //CPP二维数组初始化
    array<int, 10>MyInt1{ 11,2,3,4,5,6,7,8,9,10 }; array<int, 10>MyInt2{ 21,2,3,4,5,6,7,8,9,10 }; array<int, 10>MyInt3{ 31,2,3,4,5,6,7,8,9,10 }; array<array<int, 10>, 3>myInt{ MyInt1,MyInt2,MyInt3 }; for (auto j : myInt) { for (auto i : j) { cout << i << " "; } cout << endl; } cin.get(); }

 2. CPP别名:面试

#include <iostream>

using namespace std; //通常状况,原则上都用using取代typedef //typedef处理不了模板,处理不了命名空间,统一用using
typedef double DB;        //C风格
using DBCPP = double;    //CPP风格别名 //数组别名
typedef int a[10]; using IntArray = int[10]; //函数指针
typedef int(*p)(int a, int b);        //函数指针类型,p
using pFun = int(*)(int a, int b);    //CPP函数指针别名 //函数指针数组
typedef int(*pa[10])(int a, int b); using ppFun = int(*[10])(int a, int b); void main() { cout << sizeof(DB) << endl;       //8
    cout << sizeof(DBCPP) << endl;    //8
 IntArray int1; cout << sizeof(int1) << endl;     //40
 cin.get(); }

3. auto 使用:数组

#include <iostream>

using namespace std; //C++14自动推理返回值类型 //C++11须要指定返回值类型
auto add(int a, int b)->int        //此处int可换为decltype(a+b)
{ return a + b; } //数控科技面试题:请问f是什么?
auto (*f)()->int(*)(); //int(* (*fx)() )() //返回值是函数指针 //请推理下面pf是什么类型?
auto pf1()->auto(*)()->int(*)() { return nullptr;    //返回空指针
} auto pf2(void)->auto(*)(int x)->int(*)(int a,int b) { return nullptr;    //返回空指针
} //int(* (*)(int x) )(int a,int b) //int(* (* pf2(void) )(int x) )(int a,int b) //int(*(* (void) )(int))(int,int)
 auto go(int a, int b)->auto(*)()->int (*)(int, int(*)(int, int)); //int (* (*)() )(int, int(*)(int, int)) //int (* (* go(int a, int b) )() )(int, int(*)(int, int)) //int (* (* (int, int))(void))(int, int (*)(int,int))

void main() { cout << typeid(f).name() << endl; cout << typeid(pf1).name() << endl; cout << typeid(pf2).name() << endl; cout << typeid(go).name() << endl; cin.get(); }

4. 函数模板的别名:安全

#include <iostream> #include <array>

using namespace std; //C++14自动推理返回值类型 //C++11须要指定返回值类型
template<class T1,class T2> auto add(T1 t1, T2 t2)->decltype(t1 + t2)        //此处int可换为decltype(a+b)
{ return t1 + t2; } //函数模板的别名
template<class T> using t = T; template<class T> using tp = T*; template<class T>
void show(T tx) { t<int> t1(tx);        //一旦使用别名必须指定类型 <int>
    tp<int> tp1(&tx);    //初始化指针
    cout << t1 << " " << tp1 << endl; } template<class T> using ten = array<T, 10>; void main() { cout << add(1, 2) << endl;            //3
    cout << add(1.1, 2.2) << endl;        //3.3

    int a = 10; show(a); using IntArray = array<int, 10>;    //至关于为模板起了别名,明确地指明了类型为array<int, 10>
    array<int, 10> MyInt;                //此时array<int, 10>表明一个类型
 IntArray MyInt2; //template<class T> using t = array<T, 10>; //error C2951: 模板 声明只能在全局、命名空间或类范围内使用
    ten<int> t1{ 1,2,3,4,5,6,7,8,9,10 };//模板别名不明确类型
    for (auto i : t1) { cout << i << " "; } cin.get(); }

5. 收缩转换:函数

#include <iostream>

using namespace std; void main() { char ch1(787878); char ch2{ 787878 };    //赋初始值最好用大括号,保证数据类型安全转换
 cout << (int)ch1 << endl;    //-90 编译经过,产生溢出
    cout << (int)ch2 << endl;    //编译不经过,error C2397: 从“int”转换到“char”须要收缩转换
 cin.get(); }

6. 二进制:优化

#include <iostream>

using namespace std; void main() { int a = 0b1001; int b = 0B1101; cout << a << endl;    //9
    cout << b << endl;    //13
 cin.get(); }

7. 常量表达式constexpr :spa

#include <iostream>

using namespace std; int get1() { return 5; } constexpr int get2()    //constexpr返回值或其余表达式为常量
{ return 5; } void main() { //int a[5+get1()]; //error C2131: 表达式的计算结果不是常数
    int a[5 + get2()];    //编译成功
 cin.get(); }

 8. lambda 表达式:指针

#include <iostream>
using namespace std; void main() { [] {cout << "hello world!" << endl; }();        //解决函数怀孕现象
 auto fun = [] {cout << "hello" << endl; };        //函数指针
    fun();//调用
 [] {cout << "hello C" << endl; }();                //匿名lambda表达式
 [](char *str) {cout << str << endl; }("你好!");//带参数(匿名)
 auto fun1 = [](double a, double b) {return a + b; }; cout << fun1(10, 20.1) << endl;        //30.1
 auto fun2 = [](double a, double b)->int {return a + b; };    //指定返回值类型,->在()与{}之间
    cout << fun2(10, 20.1) << endl;        //30

    int num = 100; auto func = [](int num) {num = 5, cout << num << endl; };//遵循副本机制
    func(num);                        //5
    cout << "main=" << num << endl;    //main=100
 cin.get(); }
#include <iostream> #include <array> #include <algorithm>
using namespace std; void main() { int num1 = 100; int num2 = 99; //[]() {cout << num1 << " " << num2 << endl; }();//error C3493: 没法隐式捕获“num1”,由于还没有指定默认捕获模式
    [=]() {cout << num1 << " " << num2 << endl; }();    //100 99 //[=]() {num1=10,num2=20,cout << num1 << " " << num2 << endl; }();//error C3491: “num1”: 没法在非可变 lambda 中修改经过复制捕获
    [&]() {num1 = 10, num2 = 20, cout << num1 << " " << num2 << endl; }();//=只能读不可写;&读写外部变量
    cout << "main=" << num1 << " " << num2 << endl;        //main=10 20

    int num3 = 100; int num4 = 99; [=]()mutable {num3 = 10, num4 = 20, cout << num3 << " " << num4 << endl; }();    //10 20 mutable起到副本做用
    cout << "main=" << num3 << " " << num4 << endl;                                    //100 99

    int a = 10, b = 9, c = 8; //a可读可写,bc只可读
    [&a, b, c]() {a = 20, cout << a << " " << b << " " << c << endl; }();    //20 9 8 //mutable副本,能读能写,读的本来,写的副本
    [a, b, c]()mutable {a = 1, b = 2, c = 3, cout << a << " " << b << " " << c << endl; }();    //1 2 3 
 array<int, 10>MyInt{ 1,2,3,4,5,6,7,8,9,10 }; //lambda表达式嵌入使用
    for_each(MyInt.begin(), MyInt.end(), [](int num) {cout << num << " "; });                //显示
    cout << endl; for_each(MyInt.begin(), MyInt.end(), [](int &num) {num += 1, cout << num << " "; });    //修改
    cout << endl; for_each(MyInt.begin(), MyInt.end(), [](int num) {cout << num << " "; });                //显示
 cin.get(); }

9. 函数包装器:code

#include <iostream> #include <functional>    //函数包装器头文件

using namespace std; using std::function;    //函数包装器

void go() { cout << "go" << endl; } int ADD(int a, int b) { return a + b; } void main() { function<void(void)> fun1 = go;                                    //包装函数
 fun1(); function<void(void)> fun2 = []() {cout << "go lambda" << endl; };//包装lambda表达式
 fun2(); function<int(int, int)> fun3 = ADD; cout << fun3(10, 19) << endl; function<int(int, int)> fun4 = [](int a, int b)->int {return a + b; }; cout << fun4(10, 19) << endl; cin.get(); }

10. 模板元blog

#include <iostream>
using namespace std; int get50(int n) { if (n == 1) return 1; else if (n == 2) return 2; else
        return get50(n - 1) + get50(n - 2); } //递归调用:函数反复调用,等待返回,浪费时间较多 //模板元实现递归加速 //执行速度快,编译的时候慢,代码会增长 //把运行的时间节约在编译的时候 //常使用在递归加速,游戏优化,此处的模板元仅仅适用于C++11
template<int N>
struct data { //递归表达式
    enum { res = data<N - 1>::res + data<N - 2>::res }; }; template<>
struct data<1> { enum { res = 1 }; }; template<>
struct data<2> { enum { res = 2 }; }; void main() { cout << data<40>::res << endl;    //模板元,代码加速(将运行时间放在编译中执行)
    cout << get50(40) << endl; cin.get(); }

11. C++中的const :

#include <iostream>
using namespace std; void run1(const int *p);        //可改变地址,不可改内容
void run2(int const *p);        // void run3(int * const p);        //不可改地址,可改内容
void run4(const int * const p);    //地址内容均不能改
void run5(int const * const p);    // 
void main() { //C语言中: //const int num = 10; //*(int *)(&num) = 4; //printf("%d\n", num); //4 //const int n = 10; //int a[n]; //C++编译器自动优化,将n直接替换为10 //int a = 10; //const int n = a; //此时C++编译器不敢乱优化,不敢把n直接替换为a //int data[n]; //error C2057: 应输入常量表达式 //const int a = 10; //const int n = a; //int data[n]; //const int num = 10; //*(int *)(&num) = 3; //cout << (void *)&num << endl; //优化,强行替换为10,寄存器 //cout << *(&num) << endl; //10 //cout << num << endl; //10 //int a = 10; //const int num = a; //*(int *)(&num) = 3; //cout << (void *)&num << endl; //直接读内存,此时为变量,不敢优化 //cout << *(&num) << endl; //3 //cout << num << endl; //3

    const int num[5] = { 1,2,3,4,5 }; const int *p = num; *(int *)p = 100;        //const数组没有优化,能够间接改变
    for (auto i : num) cout << i << " ";    //100 2 3 4 5
    cout << endl; cin.get(); }

12. 智能指针:

#include <iostream> #include <memory> #include <Windows.h>    
using namespace std; void cmem() { while (1) { double *p = new double[1024 * 1024 * 10]; Sleep(3000); delete p;        //释放
        Sleep(3000); } } void autoptr() { while (1) { double *p(new double[1024 * 1024 * 10]); auto_ptr<double>autop(p);    //建立智能指针,接管这片内存,会自动回收
 Sleep(3000); } } void autoptrnew() { while (1) { Sleep(6000); unique_ptr<double>p(new double[1024 * 1024 * 10]); Sleep(6000); } } void main() { //cmem();
 autoptr(); autoptrnew(); cin.get(); }

13. 多元数组 tuple :

#include <iostream> #include <tuple>
using namespace std; //多元数组,存取不一样的数据类型
void main() { char ch = 'X'; short sh = 12; int num = 1234567; double db = 123; char *p = "calc"; tuple<char, short, int, double, char *>MyTuple(ch, sh, num, db, p); auto autov1 = get<0>(MyTuple);    //多元数组不能用for(auto i:MyTuple)的方式遍历
    cout << autov1 << endl; auto autov2 = get<1>(MyTuple); cout << autov2 << endl; auto autov3 = get<2>(MyTuple); cout << autov3 << endl; auto autov4 = get<3>(MyTuple); cout << autov4 << endl; auto autov5 = get<4>(MyTuple); cout << autov5 << endl; cin.get(); }

14. 左值引用与右值引用:

#include <iostream>
using namespace std; //C++能用引用的状况,就别用指针
void change(int & rnum) { rnum = 111; } void main0501() { //int num(10); //num是左值,有内存实体,能够赋值 int num=10; //int & rnum(num); //引用&就是变量的别名 //
    //rnum = 1; //rnum等价于num的别名 //change(num); //cout << num << endl; //111 //int num = 1; //int data = 0; //cout << (void *)&data << endl; //data = num + 1; //data = num + 2; //data = num + 3; //cout << data << endl; //右值引用
    int num = 1; int && rnum(num + 4);    //右值引用,快速备份寄存器的值。编译器会自动回收
    printf("%p\n", &rnum); //如果左值引用,须要两步:
    int data = num + 4; int &rdata(data); int a[5]{ 1,2,3,4,5 }; int *p(a); cout << *p << endl;        //1

    int * & rp(p);            //左值引用改变指针 & 放在类型与变量名之间
    rp += 1; cout << *p << endl;        //2

    int * && rrp(p + 2);    //右值引用改变指针 && //int * && rrp(&a[1]);
    cout << *rrp << endl;    //4
 cin.get(); } void showit(int && rrnum)    //右值引用
{ cout << rrnum << endl; } void main() { int a[5]{ 1,2,3,4,5 }; showit(a[3] + 2); //移动语义:将左值转化为右值(左值必定能够变为右值,右值不必定可变为左值)
    showit(move(a[3])); cin.get(); }

15. 引用的本质:

#include <iostream>
using namespace std; void main0601() { int num = 10; int data = 20; int & rnum(num);    //引用一旦初始化,就不会再引用其余变量
    rnum = data; cout << num << endl;    //20
    cout << data << endl;    //20
 cin.get(); } void main() { double db; //double & rdb; //error C2530: “rdb”: 必须初始化引用
    double & rdb(db); cout << sizeof(rdb) << endl;        //8

    struct MyStruct        //引用的本质是指针实现的,为了简化程序
 { double & rdb; }; cout << sizeof(MyStruct) << endl;    //4
 cin.get(); }

 16. 引用指针以及做为函数参数和函数返回值:

#include <iostream>
using namespace std; //改变指针,须要二级指针 //C++中可用引用
void main0701() { int a(4);            //初始化为4
    int *p(new int(5));    //开辟int大小空间,值为5
    cout << a << endl;    //4
    cout << *p << endl;    //5 //int & ra(a); //引用变量 //int * & rp(p); //引用指针 //ra = 3; //*rp = 12; //cout << a << endl; //3 //cout << *p << endl; //12

    int && rra(move(a));    //右值引用,有内存实体就直接引用,没有内存实体则新开辟内存
    int * && rrp(move(p)); rra = 1; cout << rra << endl; cout << a << endl; //int 整数类型 //int & 引用整数,本质是指针 //int && 引用整数,本质是指针,能处理左值(move) 和右值
 cin.get(); } int num1 = 10; int num2 = 20; void change(int * &rp)    //C++中能用引用就别用指针
{ rp = &num2; } void main0702() { int *p = &num1; change(p); cout << *p << endl;    //20
 cin.get(); } void main0703() { int *p(nullptr); int **pp(&p); int ** &rpp(pp);        //VS2015 C++14 //int **pp(&p); //int(** (&rpp))(pp); //VS2013 C++11
 cin.get(); } void main0704() { int ***ppp(nullptr); int *** & rppp(ppp); cin.get(); } int data1 = 10; int data2 = 20; int *p = &data1; void changeit(int ** &rpp) { *rpp = &data2; } void main0705() { int **pp = &p;    //二级指针
    cout << **pp << endl;    //10
 changeit(pp); cout << **pp << endl;    //20
 cin.get(); } //返回一个引用a
int getdata() { int num = 10; return num;        //函数返回值有副本机制
} void main0706() { cout << getdata() << endl;    //10
 cin.get(); } //函数返回值有副本机制,返回变量 //栈区,自动回收、释放,返回为指针不能指向栈区,返回为引用不能应用栈区
int & getdata1() { int num = 10; return num;        //函数返回值有副本机制
} void main0707() { int & rnum = getdata1();    //此时引用的是原来的内存,调用后已经释放
    cout << "hello" << endl; cout << rnum << endl;        //此处结果并非10

    int rnum2 = getdata1();        //拷贝到新的内存rnum2中
    cout << rnum2 << endl;        //10
 cin.get(); } int & getdata2() { int *p(new int(5));    //堆区 
    return *p; } void main0708() { int & rnum = getdata2();    //此时引用的是堆区
    cout << "hello" << endl; cout << rnum << endl;        //5
 cin.get(); } char * & getcode() { char *p = "hellohellohello";    //常量字符串-->代码区(与程序供存亡)
    return p;                        //p在栈上,但指向内容在代码区
} void main() { char * &rp = getcode();            //指针,引用p,但这个p在栈上,消亡了
    char * newp = rp;    //保存rp存储代码区地址
    cout << "hello china" << endl; cout << newp << endl;    //hellohellohello
    cout << rp << endl;        //乱码
 cin.get(); }

17. 引用数组:

#include <iostream>
using namespace std; void main0801() { int a[5]{ 1,2,3,4,5 };                            //一维数组
    int *pa[5]{ a,a + 1,a + 2,a + 3,a + 4 };        //指针数组

    int b[2][3]{ 1,2,3,4,5,6 };        //二维数组 //二维数组,每个元素是一个指针
    int *pb[2][3]{ &b[0][0],&b[0][0] + 1,&b[0][0] + 2,&b[0][0] + 3,&b[0][0] + 4,&b[0][0] + 5 }; int *p1(new int[5]{ 1,2,3,4,5 });                //堆上的一维数组
    int(*p2)[4] = new int[3][4]{ {1,2,3,4},{5,6,7,8},{9,10,11,12} };    //堆上的二维数组
 cin.get(); } void main0802() { int a[5]{ 1,2,3,4,5 }; int(&ra)[5](a);            //引用一维数组
    for (auto i : ra) cout << i << " "; cout << endl; int *pa[5]{ a,a + 1,a + 2,a + 3,a + 4 }; int *(&rpa)[5](pa);        //引用指针数组
    for (auto i : rpa) cout << *i << " "; cout << endl; cin.get(); } void main0803() { int *p1(new int[5]{ 1,2,3,4,5 }); int **pp(new int *[5]{ p1,p1 + 1,p1 + 2,p1 + 3,p1 + 4 });    //堆上指针数组
    int * &rp(p1); int ** &rpp(pp); cin.get(); } void main0804() { int b[2][3]{ 1,2,3,4,5,6 };        //二维数组 //二维数组,每个元素是一个指针
    int *pb[2][3]{ &b[0][0],&b[0][0] + 1,&b[0][0] + 2,&b[0][0] + 3,&b[0][0] + 4,&b[0][0] + 5 }; int(&rb)[2][3](b);        //引用二维数组
    int *(&rpb)[2][3](pb);    //引用二维指针数组
 cin.get(); } void main() { //int(*p2)[4] = (new int[3][4]{ { 1,2,3,4 },{ 5,6,7,8 },{ 9,10,11,12 } }); //堆上的二维数组 //指向数组的指针,用{}初始化
    int(*p2)[4]{ new int[3][4]{ { 1,2,3,4 },{ 5,6,7,8 },{ 9,10,11,12 } } }; int(*&rp)[4](p2);    //引用行指针
    for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) cout << rp[i][j]<<"   "; cout << endl; } int * (*pp)[4]{ new int *[3][4] };    //堆上开辟二维指针数组
    int * (*&rpp)[4](pp);                //引用二维指针数组
 cin.get(); }

 18. const 与引用:

#include <iostream>
using namespace std; void main0901() { int num = 100; int const & rnum(num);    //const限定引用权限,只能读不能写 //const int & rnum(num); //与上面同样 //rnum=3; //不能写
    cout << rnum << endl; cin.get(); } //void main0902() //{ // int num = 100; // int & const rnum(num); //const放在&右边没有影响 // rnum=3; // cout << rnum << endl; //
// cin.get(); //}

void main0903() { int a[5]{ 1,2,3,4,5 }; const int(&ra)[5](a);    //只能读不能写
    for (auto i : ra) cout << i << " "; cout << endl; cin.get(); } void main0904() { //int *p(new int(5)); //堆上指针初始化 //int *(&rp)(p); //*rp = 3; //cout << *p << endl;

    const int *p(new int(5));    //指针,指向常量
    const int (*(&rp))(p);        //引用一个指向常量的指针 //*rp = 3;
    cout << *p << endl; cin.get(); } void main0905() { int * const p(new int(4));    //地址不能变,值能够变
    int * const (&rp)(p);        //引用一个常量指针
    *p = 1; cin.get(); } void main0906() { const int * const p(new int(4));    //地址不能变,值也不能变
    const int * const (&rp)(p);            //引用一个指向常量的常量指针 //*p = 1;
 cin.get(); } void main() { int *p(new int(4)); //const int *(&rp)(p); //error C2440: “初始化”: 没法从“int *”转换为“const int *&”
    const int *(&rp)((const int *&)p);    //强制转换
 cin.get(); }

 19. 引用与函数指针:

#include <iostream> #include <cstdlib>
using namespace std; //函数指针引用做为参数,能够改变函数指针 //函数指针引用做为返回值,能够实现调用getitp(p)("hello world");
int gocmd(const char *cmd) { system(cmd); return 1; } int showcmd(const char *cmd) { cout << cmd << endl; return 1; } void change(int(* & p)(const char *cmd))    //函数指针的引用作参数
{ p = showcmd; } //getp()返回一个函数指针
int(*    getp()    )(const char *cmd) { int(*( p))(const char *cmd)(gocmd); return p; } //getitp()返回一个函数指针的引用,而且参数是一个函数指针的引用
int(* &   getitp(   int(*& p)(const char *cmd)    )     )(const char *cmd) { p = showcmd; return p; } void main() { int(*p)(const char *cmd)(gocmd);    //定义函数指针并初始化 //p("calc");

    ////change(p);
    //p = getp(); //经过返回值来赋值 //p("echo hello world");
 getitp(p)("hello world");    //首先getitp(p)返回一个函数指针的引用,而后继续执行后面语句
 cin.get(); }

20. 引用与指针的差异:

#include <iostream>
using namespace std; struct MyStruct { int *p1;        //4
    int & p2;        //4
    double & p3;    //4
};        //引用本质就是指针 //int & getint1() //{ // int a = 5; // return a; //返回局部变量或临时变量的地址 //}

int & getint2(int & rint)    //参数、返回都是地址,此时引用的是外部传入的参数
{ rint = 1; return rint; } void main() { //cout << sizeof(MyStruct) << endl;

    int a = 10; int *p(new int(5)); //getint2(a); //getint2(*p);

    int & ra(a);    //引用,栈上,4个字节
 cin.get(); }
相关文章
相关标签/搜索