最近开始准备春招,写博客复习下C++基本语法和一些面试题
1.获取数组中的元素个数
int arr[] = {1,2,3,4,5,6,7,8,9}; cout<<"该数组共有:"<<sizeof(arr)/sizeof(arr[0])<<endl; cout<<"数组的首地址:"<<arr<<endl; cout<<"数组元素的首地址:"<<&arr[0]<<endl;
2.数组逆序
int arr[] = {1,2,3,6,5,8}; int len = sizeof(arr)/sizeof(arr[0]),temp;//获取该数组的长度 // cout<<len; int arr2[len]; for(int i = len-1;i>=0;i--) { arr2[(len-i)-1]=arr[i]; // cout<<len-i-1<<" "; } for(int i = 0;i<len;i++){ cout<<arr2[i]<<endl; }
3.指针和引用
//在x86操作系统下,指针占4字节,在64位操作系统下指针占8字节 int a = 10; int *p = &a; //指针一定要初始化(有指向),不然变成野指针 *p = 1000; //p指向a的地址,*p代表该地址的内容,修改*p相当于修改a cout<<"此时的a值被修改为:"<<a<<endl; cout<<"sizeof(int *)"<<sizeof(p)<<endl;
//指针常量和常量指针 int a = 10; int b = 20; // 指针常量,只能修改内容,指向不可修改 int * const p = &a; *p = 100; // 常量指针,只能修改指向,不能修改内容 const int * p2 = &a; p2 = &b; // 混合方式,都不可以修改 const int * const p3 = &a;
记忆:指针常量 const修饰的是p,p指向a的地址,由于const则指向不可修改
常量指针const修饰的是*p,*p是内容,则内容不能修改
//指针和数组 int arr[] = {1,2,3,4,5,6,7,8,9,10}; int *p = arr; cout<<"数组的第一个元素:"<<*p<<endl; p++; //有一种写法是P+4,因为int占4个字节,但有潜在隐患,即不同处理机数据类型可能不一 cout<<"数组的第二个元素:"<<*p<<endl;
指针还有一个用法是解决修改形参问题,还有一种方式就是使用引用
void swap01(int *p1 , int *p2) { int temp = *p1; *p1 = *p2; *p2 = temp; }//用指针的方式 int a = 10; int b = 20; swap(&a,&b); cout<<a<<endl; cout<<b<<endl; //用引用的方式int a = 10,b=20; swap01(a,b);//通过引用来传递和用指针传递类似 cout<<a<<endl; cout<<b<<endl;
但是需要注意:
1.引用必须要初始化,2.引用一旦初始化后就无法更改(因为引用的本质其实就是:常量指针即-->type* const p) 用引用还可以实现 --->函数引用做返回值 int& test01(){//用来返回静态变量引用 static int a = 6; return a; }int& ref = test01(); cout<<"ref:"<<ref<<endl; //输出6 test01() = 666;//使用引用做返回值,那么函数可以做左值修改 cout<<"ref:"<<ref<<endl; //输出666
4.函数重载
需满足三个条件:
1.必须在同一个作用域 2.函数名相同 3.参数类型不同,或个数,或顺序不同void fun(int &a){ //调用的是变量 } void fun(const int &a){ //调用的是常量 } void func(int a){ }
5.类的访问权限
1.public 类内类外皆可访问 2.protected 类内可以,类外不可以 子可以访问父中的内容 3.private 类内可以,类外不可以 子不可以访问父中的内容 struct 默认是public class 默认是private
protected和private的主要区别在继承中体现的明显一点:
用protected继承时,派生类可以访问类内成员,而使用private继承时,派生类是访问不到类内成员的
6.类和类的各种构造函数
类成员的调用顺序是先枝干再整体,销毁顺序是先整体在枝干 比如说我写了一个Person类和Phone类,在person中用phone创建一个phone,那么调用结果如下class Phone{ public: Phone(string name) :m_PName(name) { cout<<"phone"<<endl; } string m_PName; ~Phone(){ cout<<"Phone的析构"<<endl; } }; class Person{ ~Person(){ cout<<"Person的析构"<<endl; } Person(){ cout<<"person"<<endl; } string m_name; Phone m_phone; };
C++编译器默认情况下和自动完成,1.默认构造 2.默认析构 3.默认拷贝 调用规则:1.若重写了有参构造,则编译器不再提供默认构造 2.若重写拷贝构造,则默认和有参都不再提供默认的 一般我们重写构造函数来做初始化,重写析构函数来释放堆区数据,重写拷贝构造来实现深拷贝(下图右)
浅拷贝的危害:在析构函数执行时(新开辟的指针指向员有指针的相同空间),导致该堆区数据被释放两次,导致程序奔溃