目录
选择题
编程题
36932-求最小公倍数⭐
【解题思路】
选择题
int I=1;
if(I<=0)
printf("****\n") ;
else
printf("%%%%\n");
正确答案:A
解析:
转换说明符 转换说明符 描述 %d
有符号十进制整数 %i
有符号十进制整数 %u
无符号十进制整数 %o
八进制整数 %x
十六进制整数(小写字母) %X
十六进制整数(大写字母) %f
浮点数 %e
用科学计数法表示的浮点数(小写字母e) %E
用科学计数法表示的浮点数(大写字母E) %g
根据数值的大小自动选择 %f
或%e
格式%G
根据数值的大小自动选择 %f
或%E
格式%c
单个字符 %s
字符串 %p
指针地址 %n
将已打印字符数保存在整型指针中 %%
打印一个百分号
----------------------------------------------
正确答案:B
解析:
二维数组中的每一个元素array[i],都是一个一维数组。并且都是该对应的一维数组的数组名,即首元素地址。
C语言的转义字符:
转义字符 转义字符 释义 \? 在书写连续多个问号时使用,防止他们被解析成三字母词 \' 用于表示字符常量' \“ 用于表示一个字符串内部的双引号 \\ 用于表示一个反斜杠,防止它被解释为一个转义序列符 \a 警告字符,蜂鸣 \b 退格符 \f 进纸符 \n 换行 \r 回车 \t 水平制表符 \v 垂直制表符 \ddd ddd表示1~3个八进制的数字。 如: \130 X \xdd dd表示2个十六进制数字。 如: \x30 0
class A {
……
private:
int a;
public:
const int b;
float* &c;
static const char* d;
static double* e;
};
则构造函数中,成员变量一定要通过初始化列表来初始化的是:______。
正确答案:B
解析:
- 初始化列表的位置才是真正的初始化,构造函数题中只是赋值
- 初始化列表中:只能对类中非静态的成员变量进行初始化(因为静态的成员变量是所有成员共享的 - 类外只初始化一次即可)
必须在初始化列表中初始化:(说白了就是编译器无法为我们初始化)
- const修饰的成员变量
- 引用类型的成员变量
- 类类型对象,该类没有默认的构造函数
虽然:static const char* d;里具有const但是需要注意其是static修饰的,是所有成员共享,所以必须在类外初始化。
加深理解:
编译器无法为我们初始化,那我们就可以使用C++11的补丁实现,不用我们实际写初始化列表让编译器帮我们做,但是其作为真正的初始化,性质还是不变的。class A { public: private: const int a = 0; const int& pa = a; }; int main() { A d; return 0; }
----------------------------------------------
4. 下面有关友元函数与成员函数的区别,描述错误的是?
正确答案:D
解析:
成员函数:
- 具有隐藏的this指针
- 受访问想限定符的约束
- 需要通过对象来调用
友元函数:不是成员函数 - 但是友元函数中可以访问类中私有的成员
D、不是成员函数不能以this(对象)调用
正确答案:A
解析:
用不同类型的参数使用模板时,称为模板的实例化
实例化就是实例化成为不同的对象
如一个使用了泛型模板编程的类SeqList,该SeqList并不是类型,所以是不能将SeqList用于创建对象,其仅仅是一个类模板的名字,唯有如SeqList<int>才是类型,然而这个时候就是实例化的时候,所以使用模板时,称为模板的实例化。
Widget f(Widget u)
{
Widget v(u);
Widget w=v;
return w;
}
main()
{
Widget x;
Widget y=f(f(x));
}
正确答案:D
解析:
概念:是一个特殊的构造函数,是单参的参数类型必须是类类型&,一般情况下会使用const来进行修饰。
场景:当用已经存在的对象构造新对象时,编译器会自动调用拷贝构造函数。
- 场景一:
A a1; A a2(a1); // 拷贝构造函数
- 场景二:
void Func(A a) // 传参会拷贝构造函数 {}
- 场景三
A Func() { A a; return a; // 拷贝构造函数返回一个临时对象 }
Note:
a1 = a2调用的是赋值运算符重载,因为拷贝构造函数时用已经存在的对象构造一个新对象才会调用。而Widget w=v;调用的是拷贝构造函数,不是赋值运算符重载,因为构造了一个新的对象。
题解: 经过上述推算,我们可以发现是9次,但是在编译器中类型返回的时候,当类类型作为返回值可能会优化。
编译器优化:
- 第一次优化是:
第一次调用f(x)之后返回值再调用f函数,这个时候编译器会优化位直接将第一次调用的临时对象作为第二次调用的参数(临时对象就是u作为使用)。
- 第二次优化是:
第二次调用的临时对象就作为y。
可以理解为直接少掉了临时对象,是直接进行return w;一次拷贝构造给参数Widget u / 变量Widget y。
正确答案:D
解析:
当用户定义了一个类之后,然后想要通过该类的对象直接使用某种运算符 -- 编译器是不支持的(因为:类对象中是很有可能具有多个成员,在用该类的对应进行相应的运算符操作时,该如何处理,编译器时不知道的)
悬挂引用:悬挂引用(Dangling Reference)是指在程序中使用了一个已经被释放或无效的引用。当一个引用指向一个已经被销毁的对象或者超出其作用域的对象时,就会出现悬挂引用。
悬挂引用通常发生在以下几种情况下:
- 引用指向了一个已经被删除的对象。比如,在函数中返回了一个局部变量的引用,当函数执行完毕后,该局部变量就会被销毁,引用就会成为悬挂引用。
- 引用指向了一个已经释放的内存。比如,使用delete释放了一个指针所指向的内存块,但之后仍然使用了指向该内存块的引用,这就会导致悬挂引用。
悬挂引用的问题在于,使用悬挂引用会导致未定义的行为。因为引用指向的对象已经不存在或无效,所以对悬挂引用的操作可能会访问到无效的内存,导致程序崩溃、数据损坏或其他不可预料的结果。
为了避免悬挂引用的问题,需要确保引用指向的对象在引用使用期间是有效的。可以通过合理的生命周期管理和避免返回局部对象的引用等方式来防止悬挂引用的出现。
实际场景:有关C++悬空引用的误区 - azureology - 博客园 (cnblogs.com)
A、O(n)
正确答案:A
解析:
- 建堆时间复杂度:O(n)
- 调整堆、插入、删除:O(log2n)
- 堆排序平均时间复杂度:O(nlog2n)
- 空间复杂度:O(1)
ClassA *pclassa = new ClassA[5];
delete pclassa;
正确答案:A
解析:
堆上申请空间并释放空间的方式:
new Data:
- 调用operator new(size)申请空间 - 内部封装的是malloc
- 调用Data的构造函数对申请的空间初始化
delete p:
- 调用析构函数释放p指向对象中的资源
- 调用operator delete释放p所指向的空间 - 内部封装的是free
Note:new只能申请单个元素空间,delete只能释放单个元素空间
new Data[N]:
- 调用operator new[N](size)申请空间 - 内部封装的是operator new(size)
- 调用Data的构造函数N次对申请的空间初始化
delete p:
- 调用析构函数N次释放p指向对象中的资源
- 调用operator delete[]释放p所指向的空间 - 内部封装的是operator delete
正是如此,所以上述程序会产生内存泄漏 / 程序崩溃。
正确答案:D
解析:
静态数据成员:
所有成员共享,并不属于具体的某个对象 - 在类中声明,然后需要在类外单独进行定义,一定不能在构造函数初始化链表的位置初始化。
类外访问时:
- 对象.静态成员变量
- 类名::静态成员变量
Note:静态成员变量是有一个特殊的。
class A { private: const static int a = 0; // static const int a = 0; };
是可以的!所以A是对的,这个是需要注意的。
class A { private: static int a = 0; };
就是错误的!
编程题
36932-求最小公倍数⭐
求最小公倍数_牛客题霸_牛客网 (nowcoder.com)
【解题思路】
#include<iostream>
using namespace std;
int gcd(int a, int b)
{
int r;
while(r = a%b)
{
a = b;
b = r;
}
return b;
}
int main()
{
int a,b;
while(cin >> a >> b)
{
cout << a*b/gcd(a,b) <<endl;
}
return 0;
}