选择题
- 引用可以看作一个变量的别名,定义的时候必须进行初始化(即说明是哪一个变量的别名),而指针可以不需要初始化,后期进行赋值使用
- 由于引用必须在定义的时候初始化,所以不存在空引用(必须是一个变量或者常量的别名),但指针可以是空指针,不指向任何内容
- 引用定义之后就是一个变量的别名,不可以再引用其他变量。但指针可以
int main() { int a = 10; int& ra = a; //ra是a的引用 int b = 20; ra = 20; //这里并不能让ra引用b,而是把ra所指空间的内容改为了20
函数传参的时候,函数参数可以是引用也可以是指针类型。
引用的底层是指针,所以引用传参的时候底层也是传递的地址,只是在语法角度看到的是传值
int func(int& left,int& right) { cout << "func()"<<endl; } int main() { int a = 10,b=20; func(a,b); //这里传递的其实是 a和b的地址(汇编角度) return 0; }
综上几条,答案选择E,引用其实也是传递的地址!
对于B:用一个类的对象赋值给一个另一个对象,说明另一个对象是已经存在的,所以会调用赋值运算符重载,不会调用拷贝构造!
这一题考察了构造和拷贝构造的编译器优化问题
具体的可以看这篇文章:构造和拷贝构造的优化
运算符重载指的是:定义一个类之后,如果想通过该类的对象直接使用某种运算符,编译器是不支持的,因为他不知道对于这个自定义类型这种运算表示什么具体含义。所以需要对运算符进行重载,重载类专属的运算符
运算符重载:
- 重载成类的成员函数,此时有一个默认的形参就是this,所以形参个数看上去比运算符需要的个数少1
- 重载成类的友元函数(因为需要访问到类内部成员,需要友元关系),形参必须要有一个类类型的对象!否则怎么使用该类的成员以达成重载的目的?
所以,如果用友元函数重载成一个运算符,而参数列表中没有任何参数,那么一定是重载错误的!友元函数又没有默认的this,你一个参数都没有怎么算是这个类的运算符重载?所以选D,重载错误
如果是用成员函数重载运算符,即使一个参数都不设置,也会有一个默认的this指针,也就是说至少是一个一元运算符。如果是友元函数重载运算符,一个参数都没有,就是0元运算符?那就不是运算符了(重载错误),运算符必须要有操作数哇!)
先构造的后析构,后构造的先析构
所以a先构造 b后构造
则b先析构 a后析构
选D
具体看我这篇文章呀:👉 构造函数和析构函数的顺序问题
这个题主要说一下B选项
我们知道引用就是某一块空间的另一个名字,但是如果该空间本身不属于你,而是属于错误的内存地址或者无权限的地址,那么这个引用就是悬挂引用int func(int& ref) { cout << ref << endl; //输出ref } int main() { int* ptr = nullptr; func(*ptr); //这里把ptr解引用 传递给形参ref //因为ptr不指向任何空间,所以*ptr就是一个错误的内存空间 // 而ref引用该内存空间,所以ref就是一个悬挂引用 }
编程题
1. 最小公倍数
思路1:暴力枚举
有两个数 A、B
要求A和B的最小公倍数,最小公倍数一定是大于等于这两个数的
所以我们可以从A和B中较大的那个数开始向上走,一定会遇到一个数可以整除A和B,遇到的第一个满足该条件的就是 最小公倍数
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int A,B;
//输入两个正整数
cin >> A >> B;
//死循环,遇到最小公倍数跳出
for(int i = max(A,B);;i++)
{
//如果两个都能被整除
if(i%A ==0 && i%B==0)
{
cout << i << endl;
break;
}
}
return 0;
}
思路2:最小公倍数 = 两数之积/最大公约数
-
首先求最小公约数:辗转相除法
辗转相除法例子:
A:30 B:12 n1为30 n2为12 第一次:30 % 12 = 6 此时n1变为12 , n2变为6(上一次的余数) 第二次:12 % 6 = 0 当n1%n2=0的时候,跳出循环 最大公约数就是此时的n2
-
然后返回(A*B)/ 最大公约数
#include<iostream>
using namespace std;
int main()
{
int A,B;
//输入两个正整数
cin >> A >> B;
int mul = A*B;
int ret = A%B;
while(ret)
{
A = B;
B = ret;
ret = A%B;
}
//最大公约数就是B
cout << mul/B << endl;
return 0;
}
2. 两种排序方法
这道题思路也很简单
用vector存放多个字符串
-
如果 某一次arr[i] > arr[i+1] 说明不符合字典排序
-
如果 某一次arr[i].size() > arr[i+1].size() 说明不符合长度排序
最后根据两个布尔值来判断输出什么
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
int n;
cin >> n;
vector<string> v;
v.resize(n);
for(size_t i = 0;i < v.size();++i)
{
cin >> v[i];
}
bool dict_sort = true;
bool length_sort = true;
for(size_t i = 0 ;i < v.size()-1;++i)
{
if(v[i].size() > v[i+1].size())
{
length_sort = false;
}
if(v[i] > v[i+1]) //调用string的运算符重载
{
dict_sort = false;
}
}
if(dict_sort && length_sort)
{
cout << "both" << endl;
}
else if(dict_sort)
{
cout << "lexicographically" << endl;
}
else if(length_sort)
{
cout << "lengths" << endl;
}
else
{
cout << "none" << endl;
}
return 0;
}