[day02]引用高级、类型相关的操作、enum、new/delete重载、大数运算、函数模板与自动变量、inline
1.引用高级
|
一维数组的引用 |
int main() { int a[5] = { 1, 2, 3, 4, 5 }; int(& ra)[5] = a; for (auto data : ra) { cout << data << " " << endl; } system("pause"); return 0; } |
|
二维数组的引用 |
int main() { int a[2][3] = { 1, 2, 3, 4, 5, 6 }; // int a[2] = {1, 2} --> int (&ra)[2] = a; // int a[2][3] = ... --> int (&ra)[2][3] = a; int(&ra)[2][3] = a; for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { cout << ra[i][j] << endl; } } system("pause"); return 0; } |
|
引用函数指针 |
int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int multi(int a, int b) { return a * b; } // 修改函数指针的值,通过传递函数指针的引用 void change1(int(* &r)(int, int)) { r = multi; } // 修改并返回函数指针的引用 int(* & change2(int (* &r)(int, int)))(int, int) { r = sub; return r; } // 引用函数指针 int main() { // 函数指针 int(*pAdd)(int, int) = add; cout << pAdd(1, 2) << endl; // 函数指针的引用 int(*&rAdd)(int, int) = pAdd; //int(*&&rAdd)(int, int) = &add; // 右值的引用 cout << rAdd(1, 2) << endl; // 直接修改引用的值 rAdd = sub; // 改变引用的值 // rAdd,pAdd都成了sub函数的地址 cout << rAdd(1, 2) << endl; cout << pAdd(1, 2) << endl; // 通过函数修改引用 change1(rAdd); // 不带返回值 cout << rAdd(1, 2) << endl; cout << pAdd(1, 2) << endl; cout << change2(rAdd)(1, 2) << endl; cout << pAdd(1, 2) << endl; system("pause"); return 0; } |
|
引用数组是不合法的 |
int main() { // 引用数组是不合法的 // 即数组不能用来存放引用 int a = 1, b = 2, c = 3; // int &r[3] = { a, b, c }; //引用数组不合法 int *p[3] = { &a, &b, &c }; //指针数组合法 system("pause"); return 0; } |
|
sizeof测引用的大小 |
struct mystruct { double &rd; }; // sizeof 测引用的大小 // 当单独测引用的时候,会去测引用所引用的对象实体 // 只有测结构体的时候才准确,说明引用就是使用指针实现 // 引用变量占4个字节 int main() { double d = 10.3; double &rd = d; cout << sizeof(d) << endl; // 8 cout << sizeof(rd) << endl; // 8 cout << sizeof(mystruct) << endl; // 4 system("pause"); return 0; } |
|
右值引用做函数参数 |
int getdata(int &&num) // 节约内存拷贝的开销 { num += 10; return num; } // 右值引用做函数参数 int main() { int a = 1; int b = 2; cout << getdata(a + b) << endl; system("pause"); return 0; } |
|
C++11左值转换成右值 |
// C++11左值转换成右值 std::move() int main() { int a = 1; int b = 2; cout << getdata(move(a)) << endl; system("pause"); return 0; } |
|
常量引用 |
// 常量引用 int main() { char str[4]("abc"); const char(&rstr)[4] = str; //rstr[1] = 'B'; // 错误 system("pause"); return 0; } |
|
常引用函数指针 |
// 常引用函数指针 int main9() { int(*pAdd)(int, int) = add; int(* const &rAdd)(int, int) = pAdd; // rAdd = sub; // 无法修改引用 system("pause"); return 0; } |
| 函数返回引用做左值例子 |
#include <iostream> #include <cstdlib> int &func() { static int a = 10; return a; } int main(void) { std::cout << func() << std::endl; // 10 func() = 11; std::cout << func() << std::endl; // 11 system("pause"); return 0; } |
| 使用字面量对常引用初始化 |
int main(void) { //int &ra = 10; //无法从“int”转换为“int &” const int &ra = 10; // OK std::cout << ra << std::endl; std::cout << &ra << std::endl; system("pause"); return 0; } |
| 注:1.当使用常量(字面量)对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名 2.使用常量对const引用初始化后将生成一个只读变量 |
2.类型相关的操作
|
获取变量的类型 |
typeid(var).name()
|
|
根据一个变量的类型构造一个变量 |
decltype(var) varname;
|
3.enum
|
C语言中的enum(弱类型) |
#include <stdio.h> #include <stdlib.h> enum color {red, yellow, blue, white}; int main() { // 定义一个enum变量 enum color mycolor = red; // 定义变量也必须写全前面的enum关键字 mycolor = 10; // C语言弱类型,可以随便赋值 printf("%d\n", mycolor); mycolor = 'A'; printf("%d\n", mycolor); system("pause"); return 0; } |
|
C++中的enum(强类型) |
#include <iostream> #include <cstdlib> #include <cstdio> // 限定类型为char enum color : char{red='A', blue, yellow, white}; int main() { color mycolor; // 定义变量可以不需要enum关键字 //mycolor = 'A'; //mycolor = 1; //强类型,两者都失败 //可以使用以下两种方式赋值 mycolor = color::red; mycolor = red; printf("%d, %c\n", mycolor, mycolor); system("pause"); return 0; } |
4.new/delete重载
|
实现对全局局部的new/delete重载 |
#include <iostream> #include <cstdlib> // 全局new的重载 void *operator new (size_t size) { void *p = NULL; if (size != 0) p = malloc(size); std::cout << "全局new" << std::endl; return p; } // 全局delete重载 void operator delete (void *p) { if (p != NULL) free(p); std::cout << "全局delete" << std::endl; } // 全局new[]的重载 void *operator new[](size_t size) { std::cout << "全局new[]的重载" << std::endl; return operator new (size); } // 全局delete[]的重载 void operator delete[](void *p) { std::cout << "全局delete[]的重载" << std::endl; return operator delete(p); } class MyClass { public: int var; MyClass() { std::cout << "构造函数" << std::endl; } ~MyClass() { std::cout << "析构函数" << std::endl; } // 局部new static void *operator new (size_t size){ std::cout << "局部new" << std::endl; MyClass *p = ::new MyClass; return p; } // 局部delete static void operator delete (void *p) { std::cout << "局部delete" << std::endl; ::delete p; } // 局部new[]的重载 void *operator new[](size_t size) { std::cout << "局部new[]的重载" << std::endl; return operator new (size); } // 局部delete[]的重载 void operator delete[](void *p) { std::cout << "局部delete[]的重载" << std::endl; return operator delete(p); } }; int main(void) { //int *p = new int[10]; //delete []p; MyClass *myClass = new MyClass[5]; delete myClass; system("pause"); return 0; } |
|
new/delete调用顺序 |
![]() |
5.大数运算
|
大数加法 |
void ptBigAdd01(const char * const inStr1, const char * const inStr2, char * const outStr) { int len1 = strlen(inStr1); int len2 = strlen(inStr2); int lenMax = len1 > len2 ? len1 : len2; int *inNum1 = (int *)malloc(sizeof(int) * (lenMax+1)); int *inNum2 = (int *)malloc(sizeof(int) * len2); int i, j, k; memset(inNum1, 0, sizeof(int)* (lenMax + 1)); memset(inNum2, 0, sizeof(int)* len2); if (len1 > len2) { for (i = len1 - 1, j = 0; i >= 0; i--, j++) inNum1[j] = inStr1[i] - 48; for (i = len2 - 1, j = 0; i >= 0; i--, j++) inNum2[j] = inStr2[i] - 48; } else { for (i = len2 - 1, j = 0; i >= 0; i--, j++) inNum1[j] = inStr2[i] - 48; for (i = len1 - 1, j = 0; i >= 0; i--, j++) inNum2[j] = inStr1[i] - 48; } for (i = 0; i<len1 + len2 - lenMax; i++) { inNum1[i] += inNum2[i]; if (inNum1[i] >= 10) { inNum1[i] -= 10; inNum1[i + 1] ++; } } for (i = lenMax; inNum1[i] == 0; i--); // The result is 0 if (i == -1) printf("0"); for (j = i, k=0; j >= 0; j--, k++) { //printf("%d", inNum1[j]); outStr[k] = inNum1[j] + 48; } free(inNum1); free(inNum2); } |
|
大数减法 |
void ptBigSub(const char * const inStr1, const char * const inStr2, char *const outStr) { int len_min = strlen(inStr1); int len_max = strlen(inStr2); int last_j = 0; //最关键的错位 while (len_min > 0) { int dd1 = inStr1[len_min - 1] - '0'; int dd2 = inStr2[len_max - 1] - '0'; if (last_j) dd2 = dd2 - 1; last_j = dd2 >= dd1 ? 0 : 1; dd2 = dd2 >= dd1 ? dd2 : dd2 + 10; outStr[len_max] = (dd2 - dd1) + '0'; len_max--; len_min--; } while (len_max > 0) { int dd2 = (outStr[len_max - 1] - '0'); if (last_j) dd2 = dd2 - 1; last_j = dd2 >= 0 ? 0 : 1; dd2 = dd2 >= 0 ? dd2 : dd2 + 10; outStr[len_max] = dd2 + '0'; len_max--; } if (last_j) outStr[0] = '1'; else outStr[0] = '0'; } |
|
大数乘法 |
void ptBigMulti(const char * const inStr1, const char * const inStr2, char *const outStr) { int len1 = strlen(inStr1); int len2 = strlen(inStr2); int *res = (int *)malloc(sizeof(int)* (len1 + len2)); int i, j, k; memset(res, 0, sizeof(int)* (len1 + len2)); for (i = 0; i < len1; i++) { for (j = 0; j < len2; j++) { res[i + j + 1] += (inStr1[i] - 48) * (inStr2[j] - 48); } } for (i = len1 + len2 - 1; i >= 0; i--) { if (res[i] >= 10) { res[i - 1] += res[i] / 10; res[i] %= 10; } } for (i = 0; res[i] == 0; i++); for (j = i, k=0; j < len1 + len2; j++, k++) { outStr[k] = res[j] + 48; } free(res); } |
6.函数模板与自动变量
|
求任意类型数组的最大值 |
template<typename T> T getMax(const T * const arr, const int n) { T maxVal(arr[0]); for (int i = 1; i < n; i++) { if (arr[i] > maxVal) maxVal = arr[i]; } return maxVal; } // 函数模板,求任意类型数组的最大值 int main(void) { int arr[5] = { 3, 1, 2, 4, 8 }; std::cout << getMax(arr, 5) << std::endl; system("pause"); return 0; } |
|
求可变参数的和 |
// 可变参 // 必须至少要指定一个模板类型的形参变量 // NT getSum(int count, ...)这样是不行的 template<typename NT> NT getSum(int count, NT data, ...) { NT sum(0); va_list arg_ptr; va_start(arg_ptr, count); for (int i = 0; i < count; i++) { sum += va_arg(arg_ptr, NT); } va_end(arg_ptr); return sum; } //函数模板,求可变参数的和 int main(void) { std::cout << getSum(5, 1, 2, 3, 4, 5) << std::endl; system("pause"); return 0; } |
|
根据实际推导出类型 |
// 一般来说以下两者(typename,class)没区别 //template<typename T1, typename T2> template<class T1, class T2> auto getMulti(T1 a, T2 b)->decltype(a * b) { return a * b; } // 根据实际推导出类型 int main(void) { std::cout << typeid(getMulti(1.1, 2)).name() << std::endl; system("pause"); return 0; } |
|
注:函数参数不能用auto |
7.inline
|
inline函数的限制 |
|
(1) 不能有递归 (2) 不能包含静态数据 (3) 不能包含循环 (4) 不能包含switch和goto语句 (5) 不能包含数组 注:若一个内联函数定义不满足以上限制,则编译系统把它当作普通函数对待。 |

浙公网安备 33010602011771号