更多 C++ 惯用法/资源返回
外观
在工厂函数的返回类型中明确地传达资源所有权的转移。
工厂函数通常用于创建新的资源并将其返回给调用方。新的资源可以是原始内存、动态分配的对象、数据库游标/连接、锁等等。关于资源的一个重要问题是,谁拥有资源,谁释放资源?很多时候,接口都是以调用方隐式负责资源释放的方式开发的。如果调用方没有意识到这一点,或者只是忘记了采取正确的步骤,就会导致一种易于错误使用的接口。以下代码片段展示了一个例子。
struct X
{
void foo() {}
};
X * Xfactory() // Resource ownership implicitly transferred to the caller.
{
return new X; // Dynamically allocated instance
}
int main (void)
{
Xfactory()->foo(); // Dynamically allocated instance of X leaks here
}
资源返回惯用法提供了不同的替代方案来纠正这种情况,并导致(某种程度上)难以错误使用的接口。
解决方案是将资源封装在一个资源管理智能指针中,并返回智能指针而不是原始指针。最简单的资源返回惯用法形式在下面的代码片段中显示。
struct X
{
void foo() {}
};
std::unique_ptr<X> Xfactory() // Resource ownership explicitly transferred to the caller.
{
return std::unique_ptr<X> (new X); // Dynamically allocated instance
}
int main (void)
{
Xfactory()->foo(); // Dynamically allocated instance of X does not leak here
}
在确定要使用的资源管理智能指针类型以返回资源时,需要考虑几个问题。可能的选择是
std::auto_ptr- boost::shared_ptr / std::shared_ptr(从 C++11 开始)
- C++0x 中的 std::unique_ptr
- 用户定义的 句柄/体 惯用法
Scott Meyers 在他的文章 The Resource Return Problem 中对选择一种而不是另一种的优缺点进行了详细的讨论。只要不需要自定义删除功能(除了普通的旧 delete),auto_ptr 是一种快速使用资源返回惯用法的方式,如上所示。auto_ptr 提供了资源的独占但可转移的所有权,这仅仅通过查看接口就变得非常清楚。对于动态分配的指针返回工厂函数,boost::shared_ptr 也是一个不错的选择,因为它提供了正常的复制语义(例如,它可以存储在 STL 容器中)。它还允许将资源释放策略从正常的删除操作更改为自定义删除,而不会影响客户端。
在资源返回惯用法涉及独占所有权的情况下,移动构造函数 惯用法在转移资源所有权时经常很有用。