lock_guard是RAII实现还是用于实现RAII
Is lock_guard a RAII implementation or it is used to implement RAII?
维基百科(和其他一些来源)声明:
在RAII中,持有资源与对象生命周期相关联:资源分配(获取)是在对象创建(特别是初始化)期间由构造函数完成的,而资源释放(释放)是在对象销毁期间由析构函数完成的。如果对象被正确地析构,就不会发生资源泄漏。
但是,wiki上的例子显示的代码根本没有显示对象的构造函数/析构函数:
#include <string>
#include <mutex>
#include <iostream>
#include <fstream>
#include <stdexcept>
void write_to_file (const std::string & message) {
// mutex to protect file access
static std::mutex mutex;
// lock mutex before accessing file
std::lock_guard<std::mutex> lock(mutex);
// try to open file
std::ofstream file("example.txt");
if (!file.is_open())
throw std::runtime_error("unable to open file");
// write message to file
file << message << std::endl;
// file will be closed 1st when leaving scope (regardless of exception)
// mutex will be unlocked 2nd (from lock destructor) when leaving
// scope (regardless of exception)
}
我找到的lock_guard的定义也引用了它是"RAII-style":
lock_guard类是一个互斥锁包装器,它提供了一种方便的raii风格机制,用于在一个作用域块的持续时间内拥有一个互斥锁。
在这个例子中,RAII是在互斥锁类上实现的,还是在lock_guard类中实现的?或者根本没有在类上实现?
RAII是c++中构造函数和析构函数的一种用法,用于确保成功的获取操作不会被撤销。典型的例子是锁的获取和释放。
class mutex_guard {
public:
explicit mutex_guard(mutex& lock): m_lock(lock) {
m_lock.acquire();
}
~mutex_guard() { m_lock.release(); }
private:
mutex& m_lock;
};
当创建mutex_guard
的实例时,它会获取锁或者失败(如果mutex::acquire
抛出)。如果成功,则完全实例化guard对象,并保证调用它的析构函数。因此,如果互斥锁被成功获取,则保证了对mutex::release
的调用。
规范的实现是保证一个完全构造的对象在离开作用域时总是被销毁,以确保获得的资源总是被释放。从这个意义上说,它使用对象和实例生命周期的标准保证来实现RAII习惯用法的需求。
这是lock_guard
谁提供RAII 同步在你发布的片段。mutex
本身不遵循RAII习惯用法。RAII不必由单独的对象提供。例如,std::ofstream
为文件输出操作提供了功能,而RAII 为文件状态openclose
提供了功能。这是留给设计师的自由吗?
RAII = Resource Acquisition Is Initialization
ie对象创建意味着资源获取,对象销毁意味着资源销毁。如果您在其他地方进行获取或销毁,那么您就没有使用RAII。
可以在RAII中使用对象的构造函数和析构函数。事实上,这是习语最常见的用法之一。例如,一个非常非常简单的智能指针(可能是RAII的典型例子)可以像下面这样实现(live on ideone):
#include <iostream>
template<typename T>
class RAIIpointer
{
private:
T* _raw_pointer;
public:
explicit RAIIpointer(T* managed): _raw_pointer(managed) // acquiring resource
{
std::cout << "ttAllocating memory for single objectn";
}
~RAIIpointer() // releasing resource
{
std::cout << "ttReleasing memory for single objectn";
delete _raw_pointer;
}
};
template<typename T>
class RAIIpointer<T[]> // array specialization
{
private:
T* _raw_pointer;
public:
explicit RAIIpointer(T* managed): _raw_pointer(managed) // acquiring resource
{
std::cout << "ttAllocating memory for arrayn";
}
~RAIIpointer() // releasing resource
{
std::cout << "ttReleasing memory for arrayn";
delete[] _raw_pointer;
}
};
int main()
{
std::cout << "Before entering RAII scopen";
{
std::cout << "tCreating a smart pointer...n";
RAIIpointer<int> smart_ptr(new int); // that's it, automatic release when scope ends
RAIIpointer<int[]> smart_ptr_arr(new int[42]); // same
std::cout << "tDone with itn";
}
std::cout << "After exiting RAII scopen";
}
你可以在这里清楚地看到tor和dtor是如何执行分配/释放的。它对客户端是完全透明的(这里是主要功能)。这正是std::lock_guard
背后的思想:它的构造函数获取std::mutex
,当对象超出作用域时,它的析构函数释放它。
- 具有瞬态资源的RAII类
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 在文件夹迭代上实现 RAII
- 范围互斥锁的自定义RAII c++实现
- 如何实现RAII +延迟初始化
- 通过构造函数和析构函数实现 RAII 是否被认为是糟糕的"现代C++"?
- 是否有任何已实现的 RAII 文件句柄
- lock_guard是RAII实现还是用于实现RAII