C++ 需要注意的知识点
2. #include <> 和 “ ” 的区别
3. 无符号和有符号都有1、2、4字节的结构,什么时候用无符号数?什么时候用有符号数?
4. #pragma pack(push,packing) #pragma pack(pop,packing)
#pragma pack(1)
#include <winsock2.h> #pragma comment(lib,"ws2_32")
5. typedef 和 #define 的区别
6. 不同文件里包含同一命名空间
8. memset 和 malloc 使用区别?
9. malloc free 和 new delete 的区别?
new 与 malloc 的区别在于,new在分配完内存之后会调用构造函数。
10. 深拷贝和浅拷贝的区别?
主要区别在于内存是否独立
-
浅拷贝:只复制了指针地址 → 两个对象指向同一块资源,容易二次释放、悬挂指针
-
深拷贝:复制对象时,分配新内存,再拷贝指针指向的数据 → 对象互相独立,销毁时不会互相影响
什么时候用深拷贝?拷贝指针的时候,B浅拷贝A,如果A被释放了,那么再调用B就会崩溃。需要深拷贝重新给B申请一块内存。
拷贝构造 和 移动构造 的区别?
关键区别:用左值(拷贝构造)还是右值(移动构造)去初始化对象
- 左值:有名字、能取地址、能在“=”号左边出现的对象。
- 右值:临时对象、字面量、
std::move之后的东西 -
拷贝构造:用一个已经存在的对象去初始化另一个正在创建的对象 复制 → 可能是浅拷贝或深拷贝。
- 语法特征
ClassName(const ClassName& other)
- 触发时机
- ClassName b = a;
- func(ClassName obj) 参数按值传递
- ClassName retVal func() 函数返回值
- 语法特征
(区别于拷贝赋值运算符:ClassName& operator=(const ClassName& other); a = b;
把一个已经存在的对象 赋值给 另一个已经存在的对象)
-
移动构造:用临时对象去初始化新对象 转移 → 偷资源,原对象清空。
- 语法特征:MyClass a(); MyClass b = a();
附加题:区分默认构造、拷贝构造、移动构造、拷贝赋值、移动赋值
凡是“新生对象”就是构造;只有“已有对象被覆盖”才是赋值。
const 会“冻结”移动,只能回落到拷贝。
分析以下代码每个步骤属于什么构造:
Foo a; 默认构造 Foo b{}; 默认构造 C11 统一初始化 Foo a(42); 带参构造 Foo b = Foo(42); 带参构造
Foo a; Foo c = a; a有名字、有地址、可以出现在等号左边 Foo c(a); 拷贝构造 Foo d = std::move(a); 移动构造 Foo a, b; b = a; 拷贝赋值 b = std::move(a); 移动赋值 void func(Foo x); Foo a; func(a); 拷贝构造 func(std::move(a)); 移动构造 std::vector<Foo> v; v.push_back(Foo()); Foo()是临时对象,移动构造 v.push_back(a); 拷贝构造(虽然v已经存在了,
但里面的元素还不存在。push_back是将已经存在的a值拷贝到新创建的元素)
Foo make() {
Foo x;
return x;
} C17编译器会优化直接就地构造,没有拷贝/移动
Foo a = make(); 未优化,因为返回的临时值 所以是 移动构造
std::vector<Foo> v;
v.emplace_back(); 无参构造,会直接默认构造一个Foo()
11. const 加载函数前后的区别?
12. 指针的引用是什么?有什么用?
13. 用char数组千万记得加结束符'\0',否则会乱码。
14. 容易造成内存溢出的函数:
- strcpy:会将字符串复制到缓冲区,建议使用strncpy()
- strcat:会将字符串合并到缓冲区末尾,建议使用strncat()
- sprintf():跟strcpy一样
- scanf()系列
15. 避免 “野指针” 和 “悬空指针”
野指针:不知道指向了什么地址的指针,比如指针声明时没有初始化:FILE* file; file指向什么值取决于栈上的随机内容, 此时
if (file) fclose(file); 因为file确实指向了一个随机地址是非空的,此时会关闭一个莫名其妙的地址,造成崩溃。记住指针声明时必须初始化:
FILE* file = nullptr;
悬空指针:指针指向的内存已经被释放了,但是指针没有置空。如果后面不小心再次使用了该指针,就会产生未定义错误。
16. NULL 和 nullptr 的区别
17. const char* 和 string 的区别
一个是C风格字符串,一个是C++风格字符串。
string自动管理内存,使用更安全。
string 转 const char* 调用 .c_str()
const char* 转 string 调用
18. perror 和 throw 两种报错方式的区别
perror 打印出错信息到 stderr,然后程序继续跑。缺点是错误没办法往调用栈上传递,调用者必须依赖打印。
throw 把错误作为异常抛出,调用者可以选择捕获或不捕获。好处是异常安全,能优雅地传递错误信息,不和日志输出耦合。还能带自定义上下文。

浙公网安备 33010602011771号