C++ 随手笔记
1.引用
作用: 给变量起别名。
#include <iostream> int main() { int a = 10; int &b = a; b = 20; cout << a << endl; //a = 20 }
引用必须初始化,引用在初始化后不可改变(因为引用的本质是指针常量const )。
int &b; //错误,未初始化 int a = 10; itn c = 20; int &b = a; b = c; //错误,初始化后不可改变,只是个赋值操作。
引用做函数参数:
作用:函数传参时,可以利用引用让形参修饰实参。
#include <iostream> void swap(int &a, int &b) { int tmp; tme = a; a = b; b = tmp; }
引用做函数返回值:
注意:不要返回局部变量引用
用法:函数调用作为左值
int& test() { static int a = 10; return a; } int &p = test();
test() = 1000;
cout << p << endl; //p = 1000
常量引用:
使用场景:用来修饰形参,防止误操作。
void test(const int &val) { //val = 1000; 防止赋值操作 cout << vla << endl; } int a = 10; test(a);
防止函数内部修改外部的变量值,理论上就是形参传值。但是当需要传递的值比如是一个大的数组,使用该方法更快以及省内存。
2.函数提供
函数默认参数:
int test(int a, int b = 20, int c = 30) { return a +b +c; } cout << test(10) << endl; //60
注意:如果某个位置已经有了默认参数,那么从这个位置往后,从左往右都要有默认参数
int test(int a = 10, int b, int c = 30) //错误
如果函数声明和函数实现只有一个有默认参数,不能同时都有默认参数(防止两个地方定义不一致,程序产生二义性)。
int test(int a = 10, int b = 20); int test(int a, int b) { return a+b; } 或 int test(int a, int b) int test(int a= 10, int b = 20) { return a + b; }
函数占位参数:
作用:形参列表使用占位参数,用来占位,调用函数时必须填补该位置
void test(int a, int) test(10, 10) test(10) //错误 void test()int a, int = 10) //带默认参数是可行的
函数重载:
作用:函数名相同,参数类型、个数、顺序不同,提高复用性.(函数返回值不能作为重载的条件)
void test() {} void test(int a) {} void test(double a) {} void test(int a, double b) {} void test(double a, int b) test(); test(10); test(10.00); test(10, 10.00) test(10.00, 10)
注意事项:
1.引用作为重载的条件
void test(int &a) {} void test(const int &a) {} 以上是允许的,变量类型不同 int a = 10; test(a); //引用第一个 test(10);//引用第二个
2.函数重载中有默认参数
void fun(int a, int b = 10) void fun(int a) fun(10) //这个时候编译器会产生二义性 fun(10, 20)//会引用第一个
所以函数重载尽量避免使用默认参数,避免存在二义性。
3.类和对象
class和struct的区别,class默认权限是私有,struct默认是公用。
构造函数语法:
类名(){}
1.构造函数,没有返回值也不写void
2.函数名称与类名相同
3.可以有参数,因此可以发生重载
4.创建对象的自动调用构造函数
析构函数语法:
~类名(){}
1.析构函数,没有返回值也不写void
2.函数名称与类名相同,在名称前加上符号~
3.析构函数不可以有参数,因此不可以重载
4.销毁对象自动调用析构函数
class Person{ Person() {cout << "Person的构造函数" << endl;}
Person(int a) { age = a; cout << "Person的有参构造函数" << endl; } Person(const Person &p) { age = p.age; cout << "Person的拷贝构造函数" << endl; } ~Person() {cout << "Person的析构函数" << endl;}
int age; }
调用:
Person p1; //无参
Person p2(10); //有参
Person p3(p2); //构造
int mian() { Person p1(); //该行会被编译器认为是一个函数声明,不会去调用Person的构造函数 }
匿名对象:
Person p1; Person p2 = Person(10);
其中Person(10)是匿名对象,没有对象名称。特点:当前行执行结束后,系统会立即回收掉匿名对象。
不要利用拷贝构造函数来初始化匿名对象。
Person(p2), 编译器会等于是Person p2,相当于创建一个p2的对象。
拷贝构造函数调用时机“
1.使用一个已经创建完毕的对象来初始化对象
Person p1(20); Person p2(p1);
2.值传递的方式给函数参数传值
void test(Person p) { //这边Person p会调用拷贝构造函数,相当于实参p1拷贝了个副本给到p } Person p1; test(p1)
3.值方式返回局部对象
Person test() { Person p1; //局部变量会先调用构造函数
cout << "aaa" << endl; return p1; //因为p1是局部变量,所以先将p1复制一份返回,因此调用拷贝构造 } Person p = test(); //拷贝的p1赋值给p
cout << "bbb" < endl;
因此顺序:
p1构造 -> aaa -> p拷贝构造-> p1析构 -> bbb -> p析构