以下是Scope Guard的惯用C ++ 11实现,该实现在范围退出时恢复值吗?
template<typename T>
class ValueScopeGuard
{
public:
template<typename U>
ValueScopeGuard(T& value, U&& newValue):
_valuePtr(&value),
_oldValue(std::forward<U>(newValue))
{
using std::swap;
swap(*_valuePtr, _oldValue);
}
~ValueScopeGuard()
{
if(_valuePtr)
{
using std::swap;
swap(*_valuePtr, _oldValue);
}
}
// Copy
ValueScopeGuard(ValueScopeGuard const& other) = delete;
ValueScopeGuard& operator=(ValueScopeGuard const& other) = delete;
// Move
ValueScopeGuard(ValueScopeGuard&& other):
_valuePtr(nullptr)
{
swap(*this, other);
}
ValueScopeGuard& operator=(ValueScopeGuard&& other)
{
ValueScopeGuard(std::move(other)).swap(*this);
return *this;
}
private:
T* _valuePtr;
T _oldValue;
friend void swap(ValueScopeGuard& lhs, ValueScopeGuard& rhs)
{
using std::swap;
swap(lhs._valuePtr, rhs._valuePtr);
swap(lhs._oldValue, rhs._oldValue);
}
};
template<typename T, typename U>
ValueScopeGuard<T> makeValueScopeGuard(T& value, U&& newValue)
{
return {value, std::forward<U>(newValue)};
}
它可以用于临时更改值,如下所示:
int main(int argc, char* argv[])
{
// Value Type
int i = 0;
{
auto guard = makeValueScopeGuard(i, 1);
std::cout << i << std::endl; // 1
}
std::cout << i << std::endl; // 0
// Movable Type
std::unique_ptr<int> a{new int(0)};
{
auto guard = makeValueScopeGuard(a, std::unique_ptr<int>{new int(1)});
std::cout << *a << std::endl; // 1
}
std::cout << *a << std::endl; // 0
return 0;
}
这样的简单实用程序是否已经在某个地方的库中实现了?我看过Boost.ScopeExit,但它的预期用法似乎不同且更加复杂。
您的move构造函数使指针成员未初始化,因此rvalue对象最终持有一个垃圾指针,该指针在其析构函数中取消引用。那是一个错误。您应该将其初始化为,nullptr
并nullptr
在析构函数中进行检查。
对于这样的类型,我不希望移动分配是简单的交换,我希望右值最终不拥有任何东西。因此,我将改为执行这种移动,因此右值最终为空:
ValueScopeGuard& operator=(ValueScopeGuard&& other)
{
ValueScopeGuard(std::move(other)).swap(*this);
return *this;
}
这个名字makeValueScopeGuard
对我来说还不清楚,它会更改值本身,我希望它只是复制当前值并将其恢复到析构函数中。
就现有类型而言,我能想到的最接近的是Boost I / O状态保护程序,它们不会改变当前状态,它们只是复制并恢复它。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句