突破编程_C++_面试(基础知识(6))
面试题14:什么是 RAII 编程方法
RAII(Resource Acquisition Is Initialization)是C++的发明者 Bjarne Stroustrup 提出的概念,也称为资源获取就是初始化
,是一种管理资源、避免泄漏的编程方法。 它的基本思想是在对象的构造函数中获取资源,并在对象的析构函数中释放资源。通过这种方式,资源管理被封装在对象的生命周期中,从而简化了资源的获取和释放,避免了手动管理资源时可能出现的错误。
RAII 的核心思想是将资源的生命周期与对象的生命周期绑定在一起。当对象被创建时,它会自动获取所需的资源;当对象被销毁时,它会自动释放所拥有的资源。这种方式可以确保资源的正确获取和释放,避免了资源泄漏和内存泄漏等问题。
比如针对上面章节中在释放内存前有返回操作
的场景,使用 RAII 编程方法可以作如下代码调整:
#include <iostream>
class SmartVal
{
public:
SmartVal()
{
printf("automatically apply for memory\n");
m_val = new int;
}
~SmartVal()
{
if (nullptr != m_val)
{
printf("automatically release for memory\n");
delete m_val;
m_val = nullptr;
}
}
public:
int* getVal()
{
return m_val;
}
private:
int* m_val = nullptr;
};
void doSomething(int type)
{
SmartVal val;
if (0 != type)
{
return; //OK:val 申请的内存会自动释放
}
}
int main()
{
doSomething(0);
return 0;
}
上面代码的输出为:
automatically apply for memory
automatically release for memory
通过在构造函数自动申请内存,在析构函数中自动释放内存,从而避免了由于忘记正确释放内存导致内存泄漏。除了对于内存的自动管理,RAII 还可以应用于其他类型的资源管理,如文件句柄、网络连接等。通过将资源的获取和释放封装在相应的对象中,可以简化资源的管理,提高代码的可读性和可维护性。根据 RAII 编程方法, C++11 标准引入了能够自动管理动态内存的智能指针。
面试题15:如何解决智能指针的循环依赖问题
使用 weak_ptr 解决循环引用问题。循环引用是指两个或更多智能指针相互引用,形成一个闭环,导致它们的引用计数永远不会降到0,从而使得它们管理的内存无法得到释放。
使用 weak_ptr 可以打破这个循环,因为它不增加所指向对象的引用计数。当一个 shared_ptr 和一个 weak_ptr 相互引用时,只有当 shared_ptr 的引用计数变为 0 时,对象才会被销毁。而 weak_ptr 可以通过调用 lock() 方法来尝试获取一个临时的 shared_ptr,以安全地访问对象。如果对象已经被销毁,lock() 方法将返回一个空的 shared_ptr。如下为样例代码:
#include <iostream>
#include <memory>
using namespace std;
class A;
class B;
class A
{
public:
A() {}
~A()
{
printf("destroy A\n");
}
public:
void setB(shared_ptr<B> b)
{
m_b = b;
}
private:
shared_ptr<B> m_b;
};
class B
{
public:
B() {}
~B()
{
printf("destroy B\n");
}
public:
void setA(shared_ptr<A> a)
{
m_a = a;
}
private:
weak_ptr<A> m_a;
};
int main() {
shared_ptr<A> a(new A);
shared_ptr<B> b(new B);
a->setB(b);
b->setA(a);
return 0;
}
上面代码的输出为:
destroy A
destroy B