<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh">
	<id>https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=RAII</id>
	<title>RAII - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=RAII"/>
	<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=RAII&amp;action=history"/>
	<updated>2026-07-10T16:55:48Z</updated>
	<subtitle>在这个wiki上该页的修订历史</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://arolstar52-zhtest.hf.space/index.php?title=RAII&amp;diff=2463202&amp;oldid=prev</id>
		<title>imported&gt;Nullizer：​使用DisamAssist清理消歧义链接：Rust（链接至Rust (编程语言)）。</title>
		<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=RAII&amp;diff=2463202&amp;oldid=prev"/>
		<updated>2025-10-26T02:04:37Z</updated>

		<summary type="html">&lt;p&gt;使用&lt;a href=&quot;/index.php?title=User:%E6%9A%81%E6%9C%88%E5%87%9B%E5%A5%88/DisamAssist&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;User:暁月凛奈/DisamAssist（页面不存在）&quot;&gt;DisamAssist&lt;/a&gt;清理&lt;a href=&quot;https://en.wikipedia.org/wiki/%E6%B6%88%E6%AD%A7%E4%B9%89&quot; class=&quot;extiw&quot; title=&quot;wikipedia:消歧义&quot;&gt;消歧义&lt;/a&gt;链接：&lt;a href=&quot;/wiki/Rust&quot; title=&quot;Rust&quot;&gt;Rust&lt;/a&gt;（链接至&lt;a href=&quot;/wiki/Rust_(%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80)&quot; title=&quot;Rust (编程语言)&quot;&gt;Rust (编程语言)&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{noteTA&lt;br /&gt;
|G1=IT&lt;br /&gt;
}}&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;RAII&amp;#039;&amp;#039;&amp;#039;，全称&amp;#039;&amp;#039;&amp;#039;资源获取即初始化&amp;#039;&amp;#039;&amp;#039;（{{langx|en|&amp;#039;&amp;#039;&amp;#039;R&amp;#039;&amp;#039;&amp;#039;esource &amp;#039;&amp;#039;&amp;#039;A&amp;#039;&amp;#039;&amp;#039;cquisition &amp;#039;&amp;#039;&amp;#039;I&amp;#039;&amp;#039;&amp;#039;s &amp;#039;&amp;#039;&amp;#039;I&amp;#039;&amp;#039;&amp;#039;nitialization}}），它是在一些[[面向对象语言]]中的一种{{link-en|慣用法|Programming idiom}}。RAII源于[[C++]]，在[[Java]]，[[C♯|C#]]，[[D语言|D]]，[[Ada]]，[[Vala]]和[[Rust (编程语言)|Rust]]中也有应用。1984-1989年期间，[[比雅尼·斯特勞斯特魯普]]和{{link-en|安德鲁·柯尼希|Andrew Koenig (programmer)}}在设计C++异常时，为解决{{link-en|資源管理|Resource management (computing)}}时的{{link-en|異常安全|Exception safety}}性而使用了该用法&amp;lt;ref&amp;gt;[http://www.stroustrup.com/except89.pdf Exception Handling for C++] {{Wayback|url=http://www.stroustrup.com/except89.pdf |date=20141006075431 }}, 5 Handling of Destructors&amp;lt;/ref&amp;gt;，后来[[比雅尼·斯特勞斯特魯普]]将其称为RAII{{sfn|Stroustrup |1994|loc=chpt. 16.5 Resource Management|ps=. I called this technique “resource acquisition is initialization.”}}。&lt;br /&gt;
&lt;br /&gt;
RAII要求，资源的有效期与持有资源的[[对象生命周期]]严格绑定，即由对象的[[构造函数]]完成{{link-en|资源的分配|Resource allocation (computer)}}（获取），同时由[[析构函数]]完成资源的释放。在这种要求下，只要对象能正确地析构，就不会出现[[资源泄漏]]问题。&lt;br /&gt;
&lt;br /&gt;
==作用==&lt;br /&gt;
&lt;br /&gt;
RAII的主要作用是在不失代码简洁性&amp;lt;ref&amp;gt;C++ FAQ, [http://www.parashift.com/c++-faq/too-many-trycatch-blocks.html &amp;quot;I have too many try blocks; what can I do about it?&amp;quot;] {{Wayback|url=http://www.parashift.com/c++-faq/too-many-trycatch-blocks.html |date=20140511183603 }}&amp;lt;/ref&amp;gt;的同时，可以很好地保证代码的异常安全性。&lt;br /&gt;
&lt;br /&gt;
下面的C++实例说明了如何用RAII访问文件和互斥量：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;mutex&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;lt;fstream&amp;gt;&lt;br /&gt;
#include &amp;lt;stdexcept&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
void write_to_file(const std::string &amp;amp; message)&lt;br /&gt;
{&lt;br /&gt;
    // 建立文件的互斥鎖&lt;br /&gt;
    static std::mutex mutex;&lt;br /&gt;
 &lt;br /&gt;
    // 訪問文件前加鎖&lt;br /&gt;
    std::lock_guard&amp;lt;std::mutex&amp;gt; lock(mutex);&lt;br /&gt;
 &lt;br /&gt;
    // 試著打開文件&lt;br /&gt;
    std::ofstream file(&amp;quot;example.txt&amp;quot;);&lt;br /&gt;
    if (!file.is_open())&lt;br /&gt;
        throw std::runtime_error(&amp;quot;unable to open file&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    // 輸出內容&lt;br /&gt;
    file &amp;lt;&amp;lt; message &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
 &lt;br /&gt;
    // 當離開時，文件會被解構（不管是否有異常）&lt;br /&gt;
    // 互斥鎖也會被解構（不管是否有異常）&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
C++保证了所有栈对象在生命周期结束时会被销毁（即调用析构函数）{{sfn|Stroustrup|2000|loc=chpt. 14.4.1 Using Constructors and Destructors}}，所以该代码是异常安全的。无论在write_to_file函数正常返回时，还是在途中抛出异常时，都会引发write_to_file函数的[[堆栈回退]]，而此时会自动调用lock和file对象的析构函数。&lt;br /&gt;
&lt;br /&gt;
当一个函数需要通过多个局部变量来管理资源时，RAII就显得非常好用。因为只有被构造成功（构造函数没有抛出异常）的对象才会在返回时调用析构函数{{sfn|Stroustrup|2000|loc=chpt. 14.4.1 Using Constructors and Destructors}}，同时析构函数的调用顺序恰好是它们构造顺序的反序&amp;lt;ref&amp;gt;C++ FAQ,  [http://www.parashift.com/c++-faq/order-dtors-for-locals.html &amp;quot;What&amp;#039;s the order that local objects are destructed?&amp;quot;] {{Wayback|url=http://www.parashift.com/c++-faq/order-dtors-for-locals.html |date=20141009151329 }}&amp;lt;/ref&amp;gt;，这样既可以保证多个资源(对象)的正确释放，又能满足多个资源之间的依赖关系。&lt;br /&gt;
&lt;br /&gt;
由于RAII可以极大地简化资源管理，并有效地保证程序的正确和代码的简洁，所以通常会强烈建议在C++中使用它。&lt;br /&gt;
&lt;br /&gt;
==典型用法==&lt;br /&gt;
&lt;br /&gt;
RAII在C++中的应用非常广泛，如[[标准模板库|C++标准库]]中的lock_guard&amp;lt;ref&amp;gt;[http://en.cppreference.com/w/cpp/thread/lock_guard lock_guard]{{Wayback|url=http://en.cppreference.com/w/cpp/thread/lock_guard |date=20140804062820 }}&amp;lt;/ref&amp;gt;便是用RAII方式来控制互斥量:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
template &amp;lt;class Mutex&amp;gt; class lock_guard {&lt;br /&gt;
private:&lt;br /&gt;
    Mutex&amp;amp; mutex_;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    lock_guard(Mutex&amp;amp; mutex) : mutex_(mutex) { mutex_.lock(); }&lt;br /&gt;
    ~lock_guard() { mutex_.unlock(); }&lt;br /&gt;
&lt;br /&gt;
    lock_guard(lock_guard const&amp;amp;) = delete;&lt;br /&gt;
    lock_guard&amp;amp; operator=(lock_guard const&amp;amp;) = delete;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
程序员可以非常方便地使用lock_guard，而不用担心异常安全问题&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
extern void unsafe_code();  // 可能抛出异常&lt;br /&gt;
&lt;br /&gt;
using std::mutex;&lt;br /&gt;
using std::lock_guard;&lt;br /&gt;
&lt;br /&gt;
mutex g_mutex;&lt;br /&gt;
&lt;br /&gt;
void access_critical_section()&lt;br /&gt;
{&lt;br /&gt;
    lock_guard&amp;lt;mutex&amp;gt; lock(g_mutex);&lt;br /&gt;
    unsafe_code();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
实际上，[[标准模板库|C++标准库]]的实现就广泛应用了RAII，典型的如[[集合 (计算机科学)|容器]]、[[智能指针]]等。&lt;br /&gt;
&lt;br /&gt;
==RRID==&lt;br /&gt;
&lt;br /&gt;
RAII还有另外一种被称为RRID（Resource Release Is Destruction）的特殊用法{{sfn|Wilson|2004|loc=chpt. 3.4 RRID}}，即在构造时没有“获取”资源，但在析构时释放资源。ScopeGuard&amp;lt;ref&amp;gt;Andrei Alexandrescu, [http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758 Change the Way You Write Exception-Safe Code] {{Wayback|url=http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758 |date=20141024040741 }}&amp;lt;/ref&amp;gt;和Boost.ScopeExit&amp;lt;ref&amp;gt;[http://www.boost.org/doc/libs/1_56_0/libs/scope_exit/doc/html/index.html Boost.ScopeExit]{{Wayback|url=http://www.boost.org/doc/libs/1_56_0/libs/scope_exit/doc/html/index.html |date=20140925044557 }}&amp;lt;/ref&amp;gt;就是RRID的典型应用：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;functional&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class ScopeGuard {&lt;br /&gt;
private:&lt;br /&gt;
    typedef std::function&amp;lt;void()&amp;gt; destructor_type;&lt;br /&gt;
&lt;br /&gt;
    destructor_type destructor_;&lt;br /&gt;
    bool dismissed_;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    ScopeGuard(destructor_type destructor) : destructor_(destructor), dismissed_(false) {}&lt;br /&gt;
&lt;br /&gt;
    ~ScopeGuard()&lt;br /&gt;
    {&lt;br /&gt;
        if (!dismissed_) {&lt;br /&gt;
            destructor_();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void dismiss() { dismissed_ = true; }&lt;br /&gt;
&lt;br /&gt;
    ScopeGuard(ScopeGuard const&amp;amp;) = delete;&lt;br /&gt;
    ScopeGuard&amp;amp; operator=(ScopeGuard const&amp;amp;) = delete;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ScopeGuard通常用于省去一些不必要的RAII封装，例如&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void foo()&lt;br /&gt;
{&lt;br /&gt;
    auto fp = fopen(&amp;quot;/path/to/file&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
    ScopeGuard fp_guard([&amp;amp;fp]() { fclose(fp); });&lt;br /&gt;
&lt;br /&gt;
    write_to_file(fp);                     // 异常安全&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在[[D语言]]中，scope关键字也是典型的RRID用法，例如&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
void access_critical_section()&lt;br /&gt;
{&lt;br /&gt;
    Mutex m = new Mutex;&lt;br /&gt;
    lock(m); &lt;br /&gt;
    scope(exit) unlock(m);&lt;br /&gt;
&lt;br /&gt;
    unsafe_code();                  // 异常安全&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Resource create()&lt;br /&gt;
{&lt;br /&gt;
    Resource r = new Resource();&lt;br /&gt;
    scope(failure) close(f);&lt;br /&gt;
&lt;br /&gt;
    preprocess(r);                  // 抛出异常时会自动调用close(r)&lt;br /&gt;
    return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==與finally的比較==&lt;br /&gt;
&lt;br /&gt;
虽然RAII和finally都能保证资源管理时的异常安全，但相对来说，使用RAII的代码相对更加简洁。&lt;br /&gt;
如[[比雅尼·斯特劳斯特鲁普]]所说，“在真实环境中，调用资源释放代码的次数远多于资源类型的个数，所以相对于使用finally来说，使用RAII能减少代码量。”&amp;lt;ref&amp;gt;[http://www.stroustrup.com/bs_faq2.html Bjarne Stroustrup&amp;#039;s C++ Style and Technique FAQ] {{Wayback|url=http://www.stroustrup.com/bs_faq2.html |date=20200702224848 }}. [http://www.stroustrup.com/bs_faq2.html#finally &amp;quot;Why doesn&amp;#039;t C++ provide a &amp;quot;finally&amp;quot; construct?&amp;quot;] {{Wayback|url=http://www.stroustrup.com/bs_faq2.html#finally |date=20200702224848 }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在[[Java]]中使用finally来管理Socket资源&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
void foo() {&lt;br /&gt;
    Socket socket;&lt;br /&gt;
    try {&lt;br /&gt;
        socket = new Socket();&lt;br /&gt;
        access(socket);&lt;br /&gt;
    } finally {&lt;br /&gt;
        socket.close();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在采用RAII后，代码可以简化为&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
void foo() {&lt;br /&gt;
    try (Socket socket = new Socket()) {&lt;br /&gt;
        access(socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
特别是当大量使用Socket时，重复的finally就显得没有必要。&lt;br /&gt;
&lt;br /&gt;
==参考资料==&lt;br /&gt;
{{refbegin}}&lt;br /&gt;
* {{cite book|title=The C++ Programming Language|trans_title=C++程序设计语言|last=Stroustrup|first=Bjarne|authorlink=比雅尼·斯特劳斯特鲁普|year=2000|publisher=Addison-Wesley|isbn=0-201-70073-5|url=http://www.stroustrup.com/3rd.html|language=en|access-date=2014-09-29|archive-date=2014-06-30|archive-url=https://web.archive.org/web/20140630193844/http://stroustrup.com/3rd.html|dead-url=no}}&lt;br /&gt;
* {{cite book|title= The Design and Evolution of C++|trans_title= C++语言的设计和演化|last= Stroustrup|first= Bjarne|authorlink= 比雅尼·斯特劳斯特鲁普|year= 1994|publisher= Addison-Wesley|isbn= 0-201-54330-3|url= http://www.stroustrup.com/dne.html|language= en|access-date= 2014-09-29|archive-date= 2023-06-06|archive-url= https://web.archive.org/web/20230606041416/https://www.stroustrup.com/dne.html|dead-url= no}}&lt;br /&gt;
* {{cite book|title=,Imperfect C++|trans_title=Imperfect C++中文版|last=Wilson|first=Matthew|year=2004|publisher=Addison-Wesley|isbn=0321228774|url=http://www.imperfectcplusplus.com/|language=en|access-date=2023-11-10|archive-date=2023-06-05|archive-url=https://web.archive.org/web/20230605215954/https://imperfectcplusplus.com/|dead-url=no}}&lt;br /&gt;
&lt;br /&gt;
{{refend}}&lt;br /&gt;
&lt;br /&gt;
{{reflist}}&lt;br /&gt;
&lt;br /&gt;
[[Category:面向对象的程序设计]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Nullizer</name></author>
	</entry>
</feed>