C++面试
C++面试
c++面试100题
c++面试100题
1、封装多态继承
2、数据集合
3、
4、便于外部文件访问
5、只能通过对象访问
6、通过类名
7、构造函数、析构函数、拷贝构造函数、拷贝复制函数
8、将一个对象复制给新建的对象
9、没有返回值
10、类的对象中有指针,防止多个指针指向同一块内存
11、
12、类成员是const类型、类成员是引用?
13、用const修饰的对象,只能访问const函数,不能访问类的普通成员函数
14、只能在一个编译单元中使用
15、通过对象访问成员函数,函数访问非公有成员
16、被abstract修饰的类。抽象类不能实例化,只能被子类继承,子类可以实例化。【类中只有抽象函数的类叫做抽象类。抽象类不能实例化,只能被子类继承,子类可以实例化。】
17、实现类对象的运算符操作
18、【. -> ::】
19、友元
20、使用友元。
21、复制运算符简单拷贝,没有涉及内存拷贝。拷贝构造函数可以对内存进行拷贝
22、删除对象。局部类对象变量释放内存。
23、通过静态变量
24、友元对象可以访问类的私有成员
25、初始化列表的初始化顺序
26、
27、public、protected、private
28、前面指向的内存内容不能更改,可以更改指针指向的内存地址。后面指针指向的地址不能更改,地址对应内存里的内容可以更改。
29、是的
30、两个函数同名,实现函数功能不同,叫做函数重载。虚函数父类和子类函数同名,子类同名函数实现不同功能。区别在于,函数重载在同一个类中。虚函数是在基类和派生类中。
31、可以。类可以实现多种重载
32、将函数声明成静态函数。
33、前面加virtual
34、对
35、对
36、
37、是指针的大小。类占据一个内存空间
38、前面删除一个数据类型的内存。后面删除一段连续的内存
39、需要。构造子类时会构造一个父类对象。
40、优点:减小代码规模。
41、栈先进后出。栈在cpu内存中,资源少,执行速度快。堆在外部内存中,资源多。
42、类的构造函数在声明类的时候被调用。类的析构函数在对象资源被什邡市调用。都是自动调用的。
43、
44、可以根据需要实现特定的功能
45、虚拟函数可以在派生类中被实现其他函数功能。普通函数不能在派生类函数中被实现其他功能。内联函数不能被声明为虚函数。构造函数不能被声明为虚函数。不然可能出现父类对象没有被实例化,就实例化子类对象。
46、先调用构造函数后调用析构函数。当在释放派生类对象时,先执行基类的析构函数。如果析构函数不是虚函数,则子类对象资源不能被释放。
47、类的普通成员函数和友元函数
49、在构造函数中初始化和使用初始化列表初始化
50、被常引用修饰的变量或者对象不会被更改时可以使用常引用。使用常引用避免内存拷贝,消耗资源。
51、引用是变量的别名。指针一个指向的是内存的地址的变量。
52、
54、全局变量在数据区中,在堆中。局部变量在站中,局部变量在使用前需要初始化。
55、栈溢出原因,局部变量申请特别大的空间。堆溢出:申请的资源没有释放
56、构造函数
57、
58、浮点型
59、使用引用符号
60、C语言使用宏定义。c++使用内联函数
61、不是
62、是指针的大小。类占据一个内存空间
63、数组名是常量指针,不能被更改或执行++操作。指针变量可以被更改或执行++操作。数组名和指针都可以指向同一片内存。
64、按值传递、按指针传递、按引用传递
65、栈上分配和堆上分配
66、在C++语言中使用extern "C"修饰C代码,可以使C代码按照C语言方式编译。实现C代码和C++代码的联合编译。
67、
68、
69、
70、#include <>是从优先从系统文件中查找文件 #include ""是优先从工程文件中查找文件
71、
72、
73、宏只是简单替换,注意副作用
74、数组在做函数实参的时候会转变为什么类型,写错了吧,应该是数组在做函数形参的时候会转变为什么类型。会转变成指针类型。
75、
76、1个、4个、4个、8个
77、strcpy只能拷贝字符串,字符串需要’\0’结束符。memcpy可以拷贝字符串和内存。
78、define定义宏
79、字符常量没有结束符。字符串常量有结束符。sizeof长度相差1个。
80、全局变量优点全局可以访问。缺点:代码没有高内聚,低耦合。
81、static应用,修饰函数,该函数只能在该编译单元中被访问,作用:避免被其他文件访问到。
static修饰变量,变量为局部变量,会被编译器自动初始化。作用:不会被其他文件访问到。
82、const修饰函数。const在函数头修饰,返回的数据是不能被修改的。
const在函数尾。函数形参是不能被更改的。另外可以变成重载函数。
const修饰变量。修饰变量,该变量不能被修改。
const在类中修饰成员函数。const函数不能访问类的成员变量和成员函数。
类的成员函数可以访问const函数。
const修饰对象。该对象只能访问类的const函数
83、指针是指向内存地址的变量。可以使用指针访问内存。指针指向资源被释放后需要被置为空指针。指针可以为空指针。
84、常指针指的是使用const修饰的指针。指向常变量的指针形式为const *p,指向的变量不能被修改;可以指向其他内存。
85、函数指针是指向函数的指针。指针函数是返回类型为指针的函数。
87、debug版本用于调试,可以输出调试信息。release版本用于发布,会被优化。
88、1、指针传入函数,可以在函数中被修改值。2、传参避免传入整个数据,只传入数据的地址,避免大量拷贝。3、指针指向函数,实现指针调用不同函数。
89、static函数只能在当前编译单元中被访问。普通函数可以被其他编译单元访问
90、union会将变量成员按照字节对齐。
91、class中成员可以设置访问权限,struct中成员都是公共权限。
92、枚举类型中的数据类型为int型。
93、判断,当括号中为假时,程序停止抛出异常。
94、不可以,除非局部变量在单独的作用域中。
96、占用内存资源多的对象和变量传递时,避免数据拷贝消耗资源,需要使用引用。并且数据或对象不想被修改时,使用常引用。
97、分开便于函数被其他编译单元访问
98、
99、
100、智能指针不需要手动释放
101、
102、虚函数、派生类
103、
104
二、c++11新特性
这篇文章对c++11新特性表述的比较清楚。
C++11特性总结
三、新的认知
1、i++和++i谁是左值,谁是右值
i++是右值。为什么?因为i++计算过程为两部分:1、i=i;2、i = i +1;
假设代码为int i = 3; int data = i++; data的值为3。执行第一个语句时,i返回了一个临时变量。这个临时变量就是右值,不能对这个变量赋值。
假设代码为int i = 3; int data = i++; 分为两部分, i =i + 1, data = i; data的值为4。上述代码返回一个变量i,i不是临时变量。是左值。
2、指针指向常量字符串
int *p= nullptr;
p = "hello";
p[0] = 'H';
上述代码编译不会报错,运行还会报错。指针p指向的是常量字符串,常量字符串不能被修改。
3、c++11新增shared_ptr和unique_ptr
(单选)函数Print的功能是对自定义类型MyClass中的值进行调试打印,不会对MyClass对象进行任何修改,则下列函数声明中符合华为C++语言编程规范的是
A. void Print(std::unique_ptr obj);
B. void Print(const std::unique_ptr& obj);
C. void Print(std::shared_ptr obj);
D. void Print(const MyClass& obj);
正确答案:D
B选项是不推荐将unique_ptr作用常量传递给函数。
这次只分析B选项,
不推荐将unique_ptr作用常量传递给函数为什么
不推荐将
std::unique_ptr
作为常量传递给函数,主要是因为unique_ptr
的独占所有权特性。以下是几个关键原因:1.
unique_ptr
不能复制
std::unique_ptr
设计为独占所有权,意味着它不能被复制:void func(std::unique_ptr<int> p); // ❌ 不能传递一个已有的 unique_ptr
如果你尝试传递
unique_ptr
,编译器会报错,因为unique_ptr
没有拷贝构造函数,无法复制。2. 传递
const std::unique_ptr<T>&
可能导致误解如果你使用
const std::unique_ptr<T>&
作为参数:void func(const std::unique_ptr<int>& p);
这样虽然可以避免复制,但无法修改
unique_ptr
的所有权,也无法移动它。这种方式通常没有意义,因为unique_ptr
的主要作用是管理资源的生命周期,而const
限制了它的功能。3. 推荐的传递方式
如果你希望函数获取所有权,应该使用移动语义:
void func(std::unique_ptr<int> p); // 通过移动传递 std::unique_ptr<int> ptr = std::make_unique<int>(10); func(std::move(ptr)); // ✅ 传递所有权
如果你只是想访问
unique_ptr
指向的对象,而不改变所有权,推荐使用普通引用或裸指针:void func(const int& value); // 传递引用 void func(const int* ptr); // 传递裸指针
总结
- 不要 传递
std::unique_ptr
的常量引用,因为它限制了unique_ptr
的核心功能。- 如果需要转移所有权,使用
std::move()
传递unique_ptr
。- 如果只需要访问对象,使用普通引用或裸指针。
函数获取所有权是什么意思
在 C++ 中,函数获取所有权 指的是函数接管一个资源的生命周期,使其成为自己的管理对象。对于
std::unique_ptr
,这意味着函数将获得该智能指针的唯一所有权,并负责资源的释放。为什么需要获取所有权?
std::unique_ptr
设计为独占所有权的智能指针,意味着:
- 不能复制,只能移动(
std::move()
)。- 一旦转移所有权,原指针就变为空指针(不再持有资源)。
- 自动管理资源生命周期,函数不需要显式释放资源。
示例:传递
std::unique_ptr
获取所有权假设我们有一个函数
process()
,它需要接管std::unique_ptr<int>
的所有权:cpp
#include <iostream> #include <memory>void process(std::unique_ptr<int> p) {std::cout << "Value: " << *p << std::endl;// 当 `process()` 结束时,`p` 资源自动释放 }int main() {std::unique_ptr<int> ptr = std::make_unique<int>(42);process(std::move(ptr)); // 转移所有权if (!ptr) {std::cout << "ptr is now null." << std::endl;}return 0; }
关键点
std::move(ptr)
转移所有权,使process()
负责释放资源。ptr
在main()
中变为nullptr
,不再拥有资源。传递
const std::unique_ptr<int>&
不获取所有权如果你只是希望访问资源,而不想转移所有权,可以用引用:
void print(const std::unique_ptr<int>& p) {std::cout << "Value: " << *p << std::endl; }
这样
print()
不会获取所有权,ptr
仍然可以在main()
中使用。总结
- 获取所有权:函数接管
unique_ptr
,应使用std::move()
传递。- 访问对象但不获取所有权:使用
const std::unique_ptr<T>&
或裸指针。