C++蓝桥算法前置必备(一)

C++蓝桥算法前置必备

  • 1.C++基础回顾
    • 数组中数组名的作用
    • 函数的默认参数
    • const修饰指针
    • 2.C++中的内存分配
    • 3.C++中的引用
      • 函数做引用的参数
      • 引用做函数的返回值
      • 引用的本质
      • 4.C++中的模板

        1.C++基础回顾

        有一定的C语言基础,下面是一些基础回顾

        • while() 重在条件判断

          for( ; ; )重在计数

        • if 侧重于判断区间

          case侧重判断单个数字或字符,如果case中没有break,那么将会向下执行

          数组中数组名的作用

          1. 查看二维数组所占内存空间
          #include #include using namespace std; 
          int main() { int arr[40];
             
             cout << sizeof(arr) << endl;
              return 0;
          }
          
          1. 获取二维数组首地址
          cout << arr << endl;
          cout << &arr[0] << endl;
          

          函数的默认参数

          int func(int a, int b = 10, int c = 10) {return a + b + c;
          }
          //1. 如果某个位置参数有默认值,那么从这个位置往后,从左向右,必须都要有默认值
          //2. 如果函数声明有默认值,函数实现的时候就不能有默认参数
          int func2(int a = 10, int b = 10);
          int func2(int a, int b) {return a + b;
          }
          int main() {cout << "ret = " << func(20, 20) << endl;
          	cout << "ret = " << func(100) << endl;
          	cout << "func2 = " << func2() << endl;
          	
          	return 0;
          }
          

          const修饰指针

          看const右侧修饰的是什么,如果是指针 那就是常量指针,意思是指针指向的值不可以改,但是指针指向可以改; 如果const右侧修饰的是一个常量,那就是指针常量,意思是指针指向不可以改,但是指针指向的值可以改。后面也会遇到

          int a = 100;
          int b = 200;
          //常量指针
          	const int * p1 = &a;
          //	*p1 = 20;    报错 
          	p1 = &b;
          	
          	cout << p1 << endl;
          	cout << &b << endl;
          	
          	
          //指针常量
          	int * const p2 = &a;
          	*p2 = 30;
          //	p2 = &b;     报错 
          	cout << *p2 << endl;
          	cout << a << endl;
          

          2.C++中的内存分配

          • 内存分区的四个区域
            //全局变量
            int g_a = 10;
            int g_b = 10;
            //全局常量
            const int c_g_a = 10;
            const int c_g_b = 10;
            int main() {//局部变量
            	int a = 10;
            	int b = 10;
            	//打印地址
            	cout << "局部变量a地址为: " << (int)&a << endl;
            	cout << "局部变量b地址为: " << (int)&b << endl;
            	cout << "全局变量g_a地址为: " <<  (int)&g_a << endl;
            	cout << "全局变量g_b地址为: " <<  (int)&g_b << endl;
            		cout << "字符串常量地址为: " << (int)&"hello world" << endl;
            	cout << "字符串常量地址为: " << (int)&"hello world1" << endl;
            	cout << "全局常量c_g_a地址为: " << (int)&c_g_a << endl;
            	cout << "全局常量c_g_b地址为: " << (int)&c_g_b << endl;
            	//静态变量
            	static int s_a = 10;
            	static int s_b = 10;
            	cout << "静态变量s_a地址为: " << (int)&s_a << endl;
            	cout << "静态变量s_b地址为: " << (int)&s_b << endl;
            	const int c_l_a = 10;
            	const int c_l_b = 10;
            	cout << "局部常量c_l_a地址为: " << (int)&c_l_a << endl;
            	cout << "局部常量c_l_b地址为: " << (int)&c_l_b << endl;
            	return 0;
            }
            

            不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

            int * func()
            {int a = 10;
            	return &a;
            }
            int main() {int *p = func();
            	cout << *p << endl;
            	cout << *p << endl;
            	return 0;
            }
            

            全局区包括全局变量、静态变量和静态常量。同时该区域还包括字符串常量和其他常量。

            该区域的数据在程序结束后有操作系统释放。

            如果一定要在函数中返回局部变量的地址,那可以利用new在堆区开辟内存,堆区开辟的内存由程序员分配释放,若程序员不释放,程序结束时由操作系统回收。

            int* func()
            {int* a = new int(10);
            	return a;
            }
            int main() {int *p = func();
            	cout << *p << endl;
            	cout << *p << endl;
            	//利用delete释放堆区数据
            	delete p;
            	//cout << *p << endl; //报错,释放的空间不可访问
            	return 0;
            }
            

            在堆区开辟数组,注意和变量不同的是在释放的时候需要在delete后面加上[]

            //堆区开辟数组
            int main() {int* arr = new int[10];
            	for (int i = 0; i < 10; i++)
            	{arr[i] = i + 100;
            	}
            	for (int i = 0; i < 10; i++)
            	{cout << arr[i] << endl;
            	}
            	//释放数组 delete 后加 []
            	delete[] arr;
            	return 0;
            }
            

            3.C++中的引用

            函数做引用的参数

            函数传参时,可以利用引用的技术让形参修饰实参,其效果和指针一样。

            简单理解代码就是给例子中的变量a起了一个别名,但在形参中起的别名和main函数中的别名是一样的,其优点是可以简化指针修改实参。

            //1. 值传递
            void mySwap01(int a, int b) {int temp = a;
            	a = b;
            	b = temp;
            }
            //2. 地址传递
            void mySwap02(int* a, int* b) {int temp = *a;
            	*a = *b;
            	*b = temp;
            }
            //3. 引用传递
            void mySwap03(int& a, int& b) {int temp = a;
            	a = b;
            	b = temp;
            }
            int main() {int a = 10;
            	int b = 20;
            	mySwap01(a, b);
            	cout << "a:" << a << " b:" << b << endl;
            	mySwap02(&a, &b);
            	cout << "a:" << a << " b:" << b << endl;
            	mySwap03(a, b);
            	cout << "a:" << a << " b:" << b << endl;
            	return 0;
            }
            

            引用做函数的返回值

            一定注意,不要返回局部变量引用

            如果函数的返回值是引用,这个函数调用可以作为左值。

            //返回局部变量引用
            int& test01() {int a = 10; //局部变量
            	return a;
            }
            //返回静态变量引用
            int& test02() {static int a = 20;
            	return a;
            }
            int main() {//不能返回局部变量的引用
            	int& ref = test01();
            	cout << "ref = " << ref << endl;
            	cout << "ref = " << ref << endl;
            	//如果函数做左值,那么必须返回引用
            	int& ref2 = test02();
            	cout << "ref2 = " << ref2 << endl;
            	cout << "ref2 = " << ref2 << endl;
            	test02() = 1000; 
            	//因为函数的返回值是引用类型,所以函数可以作为左值;
            	//同时 ref2是函数的一个别名,所以当函数的值改变时,引用的别名也会改变。
            	cout << "ref2 = " << ref2 << endl;
            	cout << "ref2 = " << ref2 << endl;
            	return 0;
            }
            

            引用的本质

            引用的本质就是在C++内部实现了一个指针常量。

            意思就是指针的指向是不可以修改的,但是指针所指向的值是可以修改的。

            int* const ref == &a;  //两者是等价的
            

            下面这段代码能正确的说出 那就表明明白了。

            #include using namespace std;
            //发现是引用,转换为 int* const ref = &a;
            void func(int& ref){cout << "ref:" << ref << endl;
            	ref = 100; // ref是引用,转换为*ref = 100
            }
            int main(){int a = 10;
                cout << "a:" << a << endl;
                //自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改
            	int& ref = a; 
            	ref = 20; //内部发现ref是引用,自动帮我们转换为: *ref = 20;
                
            	cout << "a:" << a << endl;
            	cout << "ref:" << ref << endl;
                
            	func(a);
            	cout << "ref:" << ref << endl;
            	cout <<  "ref的地址:" << &ref << endl;
            	cout <<  "a的地址:" << &a << endl;
            	return 0;
            }
            

            4.C++中的模板

            目前只是简单的学习了下,方便后面在STL能够看懂并使用系统提供的模板

            函数的模板使用的关键字为template

            函数模板的语法

            T为通用的数据类型,名称可以替换,通常为大写字母

            template

            使用函数的模板有两种方式:自动类型推导(就是不指定参数的类型,让编译器自己推) 第二种是显示指定类型

            模板的目的是为了提高函数的复用性,将类型参数化

            templatevoid mySwap( T &a, T &b) {T temp = a;
            	a = b;
            	b = temp;
            }
            void test01() {int a = 10;
            	int b = 20;
            	
            //1.有参数时
            //	第一种:自动类型推导 
            	mySwap(a, b);
            	
            	//	第二种: 显示指定类型 
            	mySwap(a, b);
            	
            	cout << "a = " << a << endl;
            	cout << "b = " << b << endl;
            	
            }
            // 2、无参数时   模板必须要确定出T的数据类型,才可以使用
            templatevoid func()
            {cout << "func 调用" << endl;
            }
            void test02()
            {//func(); //错误,模板不能独立使用,必须确定出T的类型
            	func(); //利用显示指定类型的方式,给T一个类型,才可以使用该模板
            }
            int main() {test01();
            	test02();
            	
            	return 0;
            } 

            当模板无传入的形参时,模板不能独立使用,必须确定出T的类型,需要显示指定类型的方式,给T一个类型,才可以使用该模板。

            所以使用模板时必须确定出通用数据类型T,并且能够推导出一致的类型。