1. C++ 中传统指针存在什么问题?
- ①需要手动管理内存
- ②容易发生内存泄漏(忘记释放、出现异常等)
- ③释放后产生野指针
2. 为了解决传统指针的痛点,引入了什么指针?只能指针的格式怎么样?智能指针指向堆对象还是栈对象?
- 引入了智能指针(Smart Pointer):auto_ptr(有缺陷,不能用于数组,已废弃)、shared_ptr、unique_ptr
- 智能指针指向
堆对象
- 如果使用指针指针指向
栈对象
,因为栈对象本身出了作用于就会被释放,智能指针会导致再次释放,会有 double free
问题
int main() {
try {
shared_ptr<Person> p(new Person());
p->run();
throw "异常了";
} catch (...) {
cout << "异常了" << endl;
}
return 0;
}
3. 如何实现一个简单的自定义智能指针?
template <typename T>
class SmartPtr {
T *m_obj;
public:
SmartPtr(T *data): m_obj(data) {}
~SmartPtr() {
if (m_obj == nullptr) return;
delete m_obj;
}
T * operator->() {
return m_obj;
}
};
using namespace std;
int main() {
cout << 1 << endl;
{
SmartPtr<Person> sp = SmartPtr<Person>(new Person());
sp->run();
}
cout << 3 << endl;
return 0;
}
4. shared_ptr 对比 auto_ptr 有什么优点?
- 多个 shared_ptr 可以指向同一个对象,当最后一个 shared_ptr 在作用域内结束时,对象才会被自动释放
- 可以通过一个已存在的智能指针初始化一个新的智能指针
- shared_ptr 和 OC 里面的普通指针简直一模一样
5. 简述 shared_ptr 的原理
- 一个
shared_ptr
会对一个对象产生强引用(Strong reference)
- 每个对象都有个与之对应的
强引用计数
,记录着当前对象被多少个 shared_ptr 强引用在着,可以通过 shared_ptr 的 use_count 函数获得强引用计数
- 当有一个新的 shared_ptr 指向对象的时候,对象的强引用计数就会 +1
- 当有一个 shared_ptr 销毁时(比如作用域结束),对象的强引用计数就会 -1
- 当一个对象的强引用计数为 0 时(没有任何 share_ptr 指向对象时),对象就会自动销毁(析构函数调用)
int main() {
shared_ptr<Person> p1;
{
shared_ptr<Person> p2 = shared_ptr<Person>(new Person());
cout << p2.use_count() << endl;
p1 = p2;
cout << p1.use_count() << endl;
shared_ptr<Person> p3 = p2;
cout << p1.use_count() << endl;
}
cout << p1.use_count() << endl;
return 0;
}
6. 下面代码,运行会出问题吗?
int main() {
Person *p = new Person();
{
shared_ptr<Person> p1(p);
}
{
shared_ptr<Person> p2(p);
}
return 0;
}
7. 智能指针如何出现循环引用?怎么解决?
weak_ptr
会对一个对象产生弱引用
weak_ptr
可以解决 shared_ptr 的循环引用问题
8. unique_ptr(没啥用)
9. 下面代码打印什么?
#include <iostream>
using namespace std;
class Person;
class Car {
public:
int m_age;
shared_ptr<Person> m_owner;
Car() {
cout << "Car 无参数构造函数被调用" << endl;
};
Car(const Car &c) {
cout << "Car 拷贝构造函数被调用了" << endl;
}
void run() {
cout << "Car run" << endl;
}
~Car() {
cout << "~Car 析构函数被调用" << endl;
}
};
class Person {
public:
int m_height;
shared_ptr<Car> m_car;
Person() {
cout << "Person 无参数构造函数被调用" << endl;
};
Person(const Person &c) {
cout << "Person 拷贝构造函数被调用了" << endl;
}
void run() {
cout << "Person run" << endl;
}
~Person() {
cout << "~Person 析构函数被调用" << endl;
}
};
int main() {
cout << "main 1" << endl;
shared_ptr<Car> c1(new Car());
shared_ptr<Person> p2(new Person());
cout << c1->m_owner<< endl;
cout << "main 2" << endl;
return 3;
}
main 1
Car 无参数构造函数被调用
Person 无参数构造函数被调用
0x0
main 2
~Person 析构函数被调用
~Car 析构函数被调用
Program ended with exit code: 3
10. 下面代码打印什么?
#include <iostream>
using namespace std;
class Person;
class Car {
public:
int m_age;
shared_ptr<Person> m_owner;
Car() {
cout << "Car 无参数构造函数被调用" << endl;
};
Car(const Car &c) {
cout << "Car 拷贝构造函数被调用了" << endl;
}
void run() {
cout << "Car run" << endl;
}
~Car() {
cout << "~Car 析构函数被调用" << endl;
}
};
class Person {
public:
int m_height;
shared_ptr<Car> m_car;
Person() {
cout << "Person 无参数构造函数被调用" << endl;
};
Person(const Person &c) {
cout << "Person 拷贝构造函数被调用了" << endl;
}
void run() {
cout << "Person run" << endl;
}
~Person() {
cout << "~Person 析构函数被调用" << endl;
}
};
int main() {
cout << "main 1" << endl;
shared_ptr<Car> c1(new Car());
shared_ptr<Person> p2(new Person());
cout << c1->m_owner<< endl;
c1->m_owner = p2;
p2->m_car = c1;
cout << "main 2" << endl;
return 3;
}
main 1
Car 无参数构造函数被调用
Person 无参数构造函数被调用
0x0
main 2
Program ended with exit code: 3